再读vue官方文档系列文章目录
- vue组件间通信的八大方法
文章目录
前言
刚开始学vue的时候只是读了一遍官方文档,这样带来的后果是不够深入。本系列记录再次深入读vue官方文档及一些vue源码。
提示:以下是本篇文章正文内容,简单使用,下面案例可供参考
一、通信种类?
其实就是3中
- 父子通信
- 兄弟通信
- 跨代通信
二、八大通信方式
1. props和 $emit
这个使用率可能有80%了吧
- props 父->子
父组件 v-bind 动态传参 或者直接静态传参给子组件的props
<parent v-bind:propsname='响应式数据'></parent>
或者
<parent propsname='静态数据'></parent>
子组件用vm.props接收即可
源码这里不够地方了。
- $emit 子->父
子:$emit(event,args...)
父: <parent v-on:event='callback'></parent>
- $on:监听事件
- $off:移除监听事件
- $emit:触发事件
粗略讲一下原理:
- 每个vue实例都有
vm._events{eventName:[cb1,cb2,cb3,..]...}
对象,用来保存监听的事件 ,键值名为事件名,值为回调事件数组(允许多个回调) - vm.$on(event)负责把事件与回调加入events中
- $emit(event,args):触发事件,核心源码
vm._events.[event].forEach(cb=>{cb.apply(vm, args)})
本质是:子组件在父组件环境里监听一个事件,子组件触发事件时,子组件在父组件环境执行父组件的函数作为回调。
一个有趣的是子组件里面也是可以监听自己,并触发自己的回调。
methods: {
dc() {
this.$on('event',this.cbd)
this.$emit("event");
},
cbd(){
console.log('i am D');
}
},
有空把props emit 源码写一下就知道为啥了。
2. $parent和 $children
通过vm.
p
a
r
e
n
t
,
能
拿
到
父
组
件
实
例
,
v
m
.
parent,能拿到父组件实例, vm.
parent,能拿到父组件实例,vm.children 子组件实例数组,但是这个官方不推荐使用
测试了一下也能修改父组件data
3. provide和reject
官方描述
需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效
A组件
export default {
name: "",
props: [""],
provide:{
provideData:'我是A provide过来的'
},...}
BCDE组件
export default {
name: "",
props: [""],
data() {
return {
};
},
inject:['provideData'],
}
<template>
<div class="C">
我是<button @click="clickC">C</button>
{{provideData}}
<E> </E>
</div>
</template>
效果
4. ref/refs
ref:官方描述
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM
元素;如果用在子组件上,引用就指向组件实例
refs:(注意不是响应式数据)
一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。
- 本质获取本页的dom 或者本组件的子组件引用
A:
<template>
<div class="A">
我是A
<div>
<B message='我是A传过来的消息' v-on:event="cb1"></B>
<C ref='C'></C>
<p ref='p'></p>
</div>
</div>
mounted() {
console.log(this.$refs);//{C: VueComponent, p: p}
},
5. Vuex
这个都不用说了吧,跨组件通信,每个组件都可以获取到。
6. slot
只能单向传递数据
7. $attrs 和 $listeners
$attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。
当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
官网描述有点抽象,举个列子。
- A 想传两个prop a=1,和b = 2 ,
- 其中a传给子组件C ,b传给跨代子组件E,这个时候就可以用$attr
- 同时我想在E组件触发A的事件回调(和emit 一个道理)。
A:
<template>
<div class="A">
我是A
<div>
<C ref='C' a="1" b='2' v-on:Eevent='callBack'></C>
</div>
</div>
</template>
methods: {
callBack(){
console.log('我从E中触发');
}
},
C:
<template>
<div class="C">
我是<button @click="clickC">C</button>
<E v-bind="$attrs" v-on="$listeners"></E>
</div>
</template>
mounted() {
console.log(this.$attrs);//b=2
},
这里说明一下:v-bind="$attrs"
把从A接受了两个a=1,b=2, 但是a 在C组件的prop里面,所以只把b=2继续传给E组件
E:
<template>
<div class="E" @click="clickC">我是E</div>
</template>
methods: {
clickC(){
console.log(this.$attrs);//b=2
this.$listeners.Eevent()
}
},
8. localStorage和sessionStorage
这个也差不多,把信息存在localStorage,每个组件都可以获取到.
其实还有个eventBus 没在vue2官方文档看到,以后用到再说。
总结
兄弟通信 vuex跨级通信:vuex provide/inject $attrs/ $listerner
父子:上面都可以