Vue组件间通信
父传子
父给子传值,子用props收
// 父
<Son msg="hello">
// 子
props:['msg']
子传父
子组件在一个方法中用this.$emit定义自定义事件和要传递的值,父组件使用这个自定义事件,传递的值以函数参数的形式
子this.$emit定义事件并传值,父使用事件并函数参数接收
// 子
emits:['numchange'] // Vue3
method:{
add(){
this.$emit('numchange','hello')
}
}
// 父
<div @numchange="getNew"><div>
getNew(val){
console.log(val)
}
不相关组件通信
使用事件总线event.js,向外共享一个Vue实例
发送方和接收方都导入event.js
发送方bus.$emit(‘事件名称’,要发送的数据)
接收方bus.$on(‘事件名称’,事件处理函数)
// event.js
import Vue from 'vue'
export default new Vue()
// 发送方
import event from './event.js'
event.$emit('share','hello')
// 接收方
import event from './event.js'
event.$on('share',val=>{})
// 组件销毁时要off掉
beforeDestroy(){
event.$off('share',val=>{})
}
vue3中移除了$on、off和once方法
可以使用第三方接口mitt或tiny-emitter
event.js中导入,创建实例导出
发送方和接收方与上述相同
多级组件嵌套向下传(其实还是在一级一级传)
$attrs/$listeners
// 父
<Son :a="a" :b="b" @getA="getA" @getB="getB">
// 子
<grandson :a='a' @getA="getA" v-bind="$attrs">
props:['a']
emits:['getA']
// 子组件只获取了值a和方法getA
// 通过 this.$attrs可以拿到剩余值b
// 通过this.$listeners可以拿到剩余方法getB
// Vue3中移除了$listeners,数据和方法都在$attrs
// 孙
// 孙想要拿到父的b和getB则需要给子使用v-bind="$attrs"
// 孙在自己组件中使用this.$attrs就可以拿到所有数据
获取父/子组件的数据
要在mounted周期获取,不然子组件还没渲染好,没有ref
// 父组件有传来的数据的话
mounted(){
this.$parent // 拿到父组件传来的数据
}
// 获取子组件定义的数据(不需要子组件主动传递)
// 引用子组件ref,命名hello1
<Son ref="hello1">
mounted(){
this.$refs //包含子组件所有信息
}
真正的多级组件传值
provide/inject
// 这个用起来很愉快
// 最上级用provide
provide:{
info:'123'
}
// 下面的所有级都可以用inject接收
inject:['info']
但是按照上面那样用,它不是响应式的
// 改写provide变成响应式
import {computed} from 'vue'
data(){
return{
name:'123'
}
}
provide(){
return{
info:computed(()=>this.name)
}
}
组件间通信的注意事项
- 父组件传数据时静态数据不需要v-bind,动态数据要v-bind但是数组、布尔、对象、数组算js表达式,所以需要v-bind
- 如果prop传到子组件的是一个对象的话,传来的是对象引用,父组件只改变下面的某个属性子组件中是不会响应式更新的如果子组件需要在数据变化时响应式更新那只能放到computed中或者用watch深拷贝deep:true才能监听到变化
|