一、组件间通信的概念
开始之前,咱们把 组件间通信 这个词进行拆分
- 组件
- 通信
都晓得组件是 vue
最弱小的性能之一,vue
中每一个 .vue
咱们都能够视之为一个组件
通信指的是发送者通过某种媒体以某种格局来传递信息到收信者以达到某个目标。狭义上,任何信息的交通都是通信
组件间通信 即指组件 (.vue
) 通过某种形式来传递信息以达到某个目标
举个栗子
咱们在应用 UI
框架中的 table
组件,可能会往 table
组件中传入某些数据,这个实质就造成了组件之间的通信
二、组件间通信解决了什么
在现代,人们通过驿站、飞鸽传书、战火报警、符号、语言、眼神、触碰等形式进行信息传递,到了明天,随着科技程度的飞速发展,通信根本齐全利用有线或无线电实现,相继呈现了有线电话、固定电话、无线电话、手机、互联网甚至视频电话等各种通信形式
从下面这段话,咱们能够看到通信的实质是信息同步,共享
回到 vue
中,每个组件之间的都有单独的作用域,组件间的数据是无奈共享的
但理论开发工作中咱们经常须要让组件之间共享数据,这也是组件通信的目标
要让它们相互之间能进行通信,这样能力形成一个有机的残缺零碎
二、组件间通信的分类
组件间通信的分类能够分成以下
- 父子组件之间的通信
- 兄弟组件之间的通信
- 祖孙与后辈组件之间的通信
- 非关系组件间之间的通信
关系图:
## 三、组件间通信的计划
整顿 vue
中 8 种惯例的通信计划
- 通过 props 传递
- 通过 $emit 触发自定义事件
- 应用 ref
- EventBus
- $parent 或 $root
- attrs 与 listeners
- Provide 与 Inject
- Vuex
### props 传递数据
- 实用场景:父组件传递数据给子组件
- 子组件设置
props
属性,定义接管父组件传递过去的参数 - 父组件在应用子组件标签中通过字面量来传递值
Children.vue
props:{
// 字符串模式
name:String // 接管的类型参数
// 对象模式
age:{
type:Number, // 接管的类型为数值
defaule:18, // 默认值为 18
require:true // age 属性必须传递
}
}
Father.vue
组件
<Children name:"jack" age=18 />
### $emit 触发自定义事件
- 实用场景:子组件传递数据给父组件
- 子组件通过
$emit 触发
自定义事件,$emit
第二个参数为传递的数值 - 父组件绑定监听器获取到子组件传递过去的参数
Chilfen.vue
this.$emit('add', good)
Father.vue
<Children @add="cartAdd($event)" />
### ref
- 父组件在应用子组件的时候设置
ref
- 父组件通过设置子组件
ref
来获取数据
父组件
<Children ref="foo" />
this.$refs.foo // 获取子组件实例,通过子组件实例咱们就能拿到对应的数据
### EventBus
- 应用场景:兄弟组件传值
- 创立一个地方工夫总线
EventBus
- 兄弟组件通过
$emit
触发自定义事件,$emit
第二个参数为传递的数值 - 另一个兄弟组件通过
$on
监听自定义事件
Bus.js
// 创立一个地方工夫总线类
class Bus {constructor() {this.callbacks = {}; // 寄存事件的名字
}
$on(name, fn) {this.callbacks[name] = this.callbacks[name] || [];
this.callbacks[name].push(fn);
}
$emit(name, args) {if (this.callbacks[name]) {this.callbacks[name].forEach((cb) => cb(args));
}
}
}
// main.js
Vue.prototype.$bus = new Bus() // 将 $bus 挂载到 vue 实例的原型上
// 另一种形式
Vue.prototype.$bus = new Vue() // Vue 曾经实现了 Bus 的性能
Children1.vue
this.$bus.$emit('foo')
Children2.vue
this.$bus.$on('foo', this.handle)
### $parent 或 $root
- 通过独特祖辈
$parent
或者$root
搭建通信侨联
兄弟组件
this.$parent.on('add',this.add)
另一个兄弟组件
this.$parent.emit('add')
### $attrs 与 $listeners
- 实用场景:先人传递数据给子孙
- 设置批量向下传属性
$attrs
和$listeners
- 蕴含了父级作用域中不作为
prop
被辨认 (且获取) 的个性绑定 (class 和 style 除外)。 -
能够通过
v-bind="$attrs"
传⼊外部组件// child:并未在 props 中申明 foo <p>{{$attrs.foo}}</p> // parent <HelloWorld foo="foo"/>
// 给 Grandson 隔代传值,communication/index.vue
<Child2 msg="lalala" @some-event="onSomeEvent"></Child2>
// Child2 做开展
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>
// Grandson 使⽤
<div @click="$emit('some-event','msg from grandson')">
{{msg}}
</div>
### provide 与 inject
- 在先人组件定义
provide
属性,返回传递的值 - 在后辈组件通过
inject
接管组件传递过去的值
先人组件
provide(){
return {foo:'foo'}
}
后辈组件
inject:['foo'] // 获取到先人组件传递过去的值
### vuex
- 实用场景: 简单关系的组件数据传递
Vuex
作用相当于一个用来存储共享变量的容器
state
用来寄存共享变量的中央getter
,能够减少一个getter
派生状态,(相当于store
中的计算属性),用来取得共享变量的值mutations
用来寄存批改state
的办法。actions
也是用来寄存批改 state 的办法,不过action
是在mutations
的根底上进行。罕用来做一些异步操作
### 小结
- 父子关系的组件数据传递抉择
props
与$emit
进行传递,也可抉择ref
- 兄弟关系的组件数据传递可抉择
$bus
,其次能够抉择$parent
进行传递 - 先人与后辈组件数据传递可抉择
attrs
与listeners
或者Provide
与Inject
- 简单关系的组件数据传递能够通过
vuex
寄存共享的变量
## 参考文献
- https://juejin.cn/post/684490…
- https://zh.wikipedia.org/wiki…
- https://vue3js.cn/docs/zh
@JS 语音社群