文章目录
- 1.props传递数据(父向子)
- 2.$emit触发自定义事件(子向父)
- 3.ref(父子)
- 4.EventBus(兄弟组件)
- 5.parent或root(兄弟组件,有共同祖辈)
- 6.attrs和listeners(祖先向子孙)
- 7.provide与inject(祖先向子孙)
- 8.vuex(复杂型关系)
- 9.dispatch 和 broadcast (vue2已移除)
1.props传递数据(父向子)
- 适用场景:父组件传递数据给子组件
- 子组件设置props属性,定义接收父组件传递过来的参数
- 父组件在使用子组件标签中通过字面量来传递值
子组件:
props:{
name:String,
age:{
type:number,
default:18,
require:true
}
}
父组件:
<children name:"jack" age:18 />
2.$emit触发自定义事件(子向父)
- 适用场景:子组件传递数据给父组件
- 子组件通过$emit触发自定义事件,第二个参数为传递的数据
- 父组件绑定监听器获取到子组件传递过来的参数
子组件:
this.$emit('add',good)
父组件:
<father @add=“cartADD($event)” />
3.ref(父子)
- 父组件使用子组件的时候设置ref
- 父组件通过ref获取子组件数据
<children ref="foo" name:"jack" age:18 />
this.$refs.foo
4.EventBus(兄弟组件)
- 适用场景:兄弟组件传值
- 创建一个中央事件总线EventBus
- 兄弟组件通过$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].forEach((cb)=>cb(srgs))
}
}
}
main.js
Vue.prototype.$bus = new Bus() //将$bus挂载到vue实例的原型上
Vue.prototype.$bus = new Vue() //vue已经实现了bus功能
children1.js
this.$bus.$emit('foo')
children2.js
this.$bus.$on('foo',this.handle)
5.parent或root(兄弟组件,有共同祖辈)
通过共同祖辈$parent
或者$root
搭建通信桥梁
children1.js
this.$parent.$emit('foo')
children2.js
this.$parent.$on('foo',this.foo)
6.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>
7.provide与inject(祖先向子孙)
- 在祖先组件定义
provide
属性,返回传递的值 - 在后代组件通过
inject
接收组件传递过来的值
祖先组件
provide(){
return {
foo:'foo'
}
}
后代组件
inject:['foo'] // 获取到祖先组件传递过来的值
8.vuex(复杂型关系)
- 适用场景: 复杂关系的组件数据传递
Vuex
作用相当于一个用来存储共享变量的容器
state
用来存放共享变量的地方getter
,可以增加一个getter
派生状态,(相当于store
中的计算属性),用来获得共享变量的值mutations
用来存放修改state
的方法。actions
也是用来存放修改state的方法,不过action
是在mutations
的基础上进行。常用来做一些异步操作
9.dispatch 和 broadcast (vue2已移除)
vue 在2.0版本移除了 $dispatch 和 $broadcast,因为这种基于组件树结构的事件流方式会在组件结构扩展的过程中会变得越来越难维护。但在某些不使用 vuex 的情况下,仍然有使用它们的场景。所以 element ui 和 iview 等开源组件库中对 broadcast 和 dispatch 方法进行了重写,并通过 mixin 的方式植入到每个组件中。
实现 dispatch 和 broadcast 主要利用我们上面已经说过的 $parent 和 $children。
//element ui 中重写 broadcast 的源码
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
var name = child.$options.componentName;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
broadcast 方法的作用是向后代组件传值,它会遍历所有的后代组件,如果后代组件的 componentName 与当前的组件名一致,则触发 $emit 事件,将数据 params 传给它。
//element ui 中重写 dispatch 的源码
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
}
dispatch 的作用是向祖先组件传值,它会一直寻找父组件,直到找到组件名和当前传入的组件名一致的祖先组件,就会触发其身上的$emit
事件,将数据传给它。这个寻找对应的父组件的过程和$parent
类似。