组件通信(props,emit,mitt,v-model,$attrs,$refs,$parent,provide和inject)

一、props

<template>
  <h3>父组件</h3>
  <span v-if='toy'>儿子给的玩具{{toy}}</span>
  <Child :car='car' :getToy='getToy'></Child>
</template>
<script setup>
import  Child from './Child.vue'
import {ref} from 'vue'
let car=ref('宝马')
let toy=ref('')
const getToy=(value)=>{
  toy.value=value
}
</script>

<template>
  <h4>子组件父亲给的车{{props.car}}</h4>
  <button @click='getToy(toy)'> 把玩具给父亲</button>
</template>
<script setup>
import{ref,defineProps} from 'vue'
const props=defineProps(['car','getToy'])
let toy=ref('奥特曼')
</script>

二、自定义事件CustomEvent

<template>
  <h3>父组件</h3>
  <span v-if='toy'>儿子给的玩具{{toy}}</span>
  <hr>
  <Child @getToy='getToy'></Child>
</template>
<script setup>
import  Child from './Child.vue'
import {ref} from 'vue'
let toy=ref('')
const getToy=(value)=>{
  toy.value=value
}
</script>

<template>
  <h4>子组件玩具{{toy}}</h4>
  <button @click='getToy'> 把玩具给父亲</button>
</template>
<script setup>
import{ref,defineEmits} from 'vue'
const emit = defineEmits(['getToy'])
let toy=ref('奥特曼')
const getToy=()=>{
  emit('getToy',toy.value)
}
</script>

三、mitt

npm i mitt

utils/emitter.js
//引入mitt
import mitt from 'mitt';
//调用mitt得到emitter,emitter能绑定事件,触发事件
const emitter=mitt();
// //绑定事件
// emitter.on('test1',()=>{
//     console.log('test1事件被调用');
// })
// emitter.on('test2',()=>{
//     console.log('test2事件被调用');
// })
// setInterval(()=>{
//     emitter.emit('test1')
//     emitter.emit('test2')
// },1000)
// setTimeout(()=>{
//     // emitter.off('test1')
//     // emitter.off('test2')
//     emitter.all.clear()
// },5000)
export default emitter;
<template>
  <h4>子组件1玩具{{toy}}</h4>
  <p v-if='eat'>老二给的零食{{eat}}</p>
  <button @click='getToy'> 把玩具给老二</button>
</template>
<script setup>
import{ref,onUnmounted} from 'vue'
import emitter from '../../utils/emitter'
let toy=ref('奥特曼')
let eat=ref('')
const getToy = ()=>{
  emitter.emit('send-toy',toy.value)
}
emitter.on('send-eat',(value)=>{
  eat.value=value
})
onUnmounted(()=>{
  emitter.off('send-eat')
})
</script>

<template>
  <h4>子组件2零食{{eat}}</h4>
  <p v-if='toy'>老大给的玩具{{toy}}</p>
  <button @click='sendEat'> 把零食给老大</button>
</template>

<script setup>
import{ref,onUnmounted} from 'vue'
import emitter from '../../utils/emitter'
let eat=ref('奥利奥')
let toy=ref('')
emitter.on('send-toy',(value)=>{
  toy.value=value
})
const sendEat=()=>{
  emitter.emit('send-eat',eat.value)
}
onUnmounted(()=>{
  emitter.off('send-toy')
})
</script>

四、v-model

UI组件库,组件封装会用

1.v-model用在html标签上
<template>
  <h3>父组件</h3>
  <!-- v-model用在html标签上 -->
  <input type="text" :value="username" @input="$event.target.value">
  <input type="text" v-model="username">
</template>
<script setup>
import {ref} from 'vue'
let username=ref('张三')
</script>
2. v-model用在组件标签上
<template>
  <h3>父组件</h3>
  <!-- v-model用在组件标签上 -->
  <CustomInput v-model="username" />
  <!-- <CustomInput :modelValue="username" @update:modelValue="username=$event" /> -->
</template>

<script setup>
import  CustomInput from './CustomInput.vue'
import {ref} from 'vue'
let username=ref('张三')
</script>

<template>
  <input type="text" :value="props.modelValue" @input="emit('update:modelValue',$event.target.value)"><br>
</template>
<script setup>
import{ref,defineProps} from 'vue'
const props=defineProps(['modelValue'])
const emit=defineEmits(['update:modelValue'])
</script>

对于原生事件,$event就是事件对象

对于自定义事件,$event就是触发事件时,所传递的数据

<template>
  <h3>父组件</h3>
  <!-- v-model用在组件标签上 -->
  <CustomInput v-model:name="username" v-model:pass="password" />
</template>
<script setup>
import  CustomInput from './CustomInput.vue'
import {ref} from 'vue'
let username=ref('张三')
let password=ref('123456')
</script>

<template>
  <input type="text" :value="props.name" @input="emit('update:name',$event.target.value)"> 
  <br> 
  <input type="text" :value="props.pass" @input="emit('update:pass',$event.target.value)"> 
  <br> 
</template>
<script setup>
import{ref,defineProps} from 'vue'
const props=defineProps(['name','pass'])
const emit=defineEmits(['update:name','update:pass'])
</script>

五、$attrs

$attrs会自动排除props中声明的属性

<template>
  <h3>父组件</h3>
  a:{{a}}b:{{b}}c:{{c}}d:{{d}}
  <Child :a='a' :b='b' :c='c' :d='d' v-bind='{x:100,y:200}' :updateA='updateA'/>
</template>
<script setup>
import  Child from './Child.vue'
import {ref} from 'vue'
let a=ref('1')
let b=ref('2')
let c=ref('3')
let d=ref('4')
const updateA=(val)=>{
  a.value+=val
}
</script>

<template>
  <h4>子组件</h4>
  <ul>
    <li> a:{{props.a}}</li>
    <li>
      其他{{$attrs}}
    </li>
  </ul>
  <GrandChild v-bind='$attrs'/>
</template>
<script setup>
import  GrandChild from './GrandChild.vue'
import{ref,defineProps} from 'vue'
const props=defineProps(['a'])
</script>

<template>
  <h4>孙组件</h4>
  <ul>
    <li>a:{{props.a}}</li>
    <li>b:{{props.b}}</li>
    <li>c:{{props.c}}</li>
    <li>d:{{props.d}}</li>
    <li>x:{{props.x}}</li>
    <li>y:{{props.y}}</li>
  </ul>
  <button @click='updateA(6)'>更新A</button>
</template>
<script setup>
import{ref,defineProps} from 'vue'
const props=defineProps(['a','b','c','d','x','y','updateA'])
</script>

六、$refs,$parent

1.$refs
<template>
  <h3>父组件</h3>
  <button @click='changeChild1'>修改child1的玩具</button>
  <button @click='changeChild2'>修改child2的零食</button>
  <Child1 ref='child1'/>
  <Child2 ref='child2'/>
  <button @click='getAllChild($refs)'>获取所有子组件实例对象</button>
</template>
<script setup>
import  Child1 from './Child1.vue'
import  Child2 from './Child2.vue'
import {ref} from 'vue'
let child1=ref('')
let child2=ref('')
const changeChild1=()=>{
  child1.value.toy='小猪佩奇'
}
const changeChild2=()=>{
  child2.value.eat='汉堡'
}
const getAllChild=(refs)=>{
  console.log('refs',refs);
  for(let key in refs){
    refs[key].number+=3
  }
}
</script>

<template>
  <h4>子组件1玩具{{toy}}个数{{number}}</h4>
</template>
<script setup>
import{ref,defineExpose} from 'vue'
let toy=ref('奥特曼')
let number=ref(5)
defineExpose({toy,number})
</script>

<template>
  <h4>子组件2零食{{eat}} 个数{{number}}</h4>
</template>
<script setup>
import{ref,defineExpose} from 'vue'
let eat=ref('奥利奥')
let number=ref(3)
defineExpose({eat,number})
</script>
2.$parent
<template>
  <h3>父组件{{number}}</h3>
  <Child1 ref='child1'/
</template>
<script setup>
import  Child1 from './Child1.vue
import {ref} from 'vue'
let child1=ref('')
let number=ref(10)
defineExpose({number})
</script>

<template>
  <h4>子组件1玩具{{toy}}个数{{number}}</h4>
  <button @click=minusFather($parent)>修改父组件</button>
</template>
<script setup>
import{ref,defineExpose} from 'vue'
let toy=ref('奥特曼')
let number=ref(5)
const minusFather=(parent)=>{
  parent.number+=1
}
</script>

七、provide,inject

<template>
  <h3>父组件</h3>
  {{money}}
  品牌{{car.brand}}价格{{car.price}}数量{{car.count}}
  <Child />
</template>
<script setup>
import  Child from './Child.vue'
import {ref,reactive,provide} from 'vue'
let money=ref(100)
let car=reactive({
  brand:'宝马',
  price:'22w',
  count:3
})
const updateMoney=(val)=>{
  money.value-=val
}
provide('moneyContext',{money,updateMoney})
provide('car', car)
</script>

<template>
  <h4>子组件</h4>
  <GrandChild />
</template>
<script setup>
import  GrandChild from './GrandChild.vue'
</script>

<template>
  <h4>孙组件</h4>
  <p>{{money}} <button @click="updateMoney(5)">花钱</button>  </p>
  {{car.brand}}{{car.price}}{{car.count}}
</template>
<script setup>
import{ref,inject} from 'vue'
let {money,updateMoney}=inject('moneyContext',{money:0,updateMoney:()=>{}})
let car=inject('car',{brand:'xx',price:'xxx',count:'xxx'})
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值