一、 props $emit
父组件通过props向子组件传递数据,子组件通过$emit触发父组件中的方法 改变父组件的数据,符合单向数据流。
二、$listeners $attrs
$listeners 属性(它是一个对象,里面包含了作用在这个组件上的所有监听器。)
设想这样一个场景
父组件Parent 子组件A A的子组件B 如下图:
要想在B组件中改变父组件的值,要怎么办呢? 一个方法事在B组件中emit一次到A组件,再在A组件emit到父组件。
vue2.4 提供了vm.$listeners属性
我们可以在A组件中使用 v-on="$listeners"
B.vue
<z-button type="success" @click="subNum">num减少</z-button>
... // 省略
methods: {
subNum(){
this.$emit('btn2Clicked');
}
},
// B.vue
A.vue
<template>
<div>
<B v-on="$listeners"></B>
</div>
</template>
...// 省略
A.vue
Parent.vue
<template>
<A @btn2Clicked="subNum"></A>
</template>
// ...省略
methods: {
subNum(){
this.num--;
}
}
// Parent.vue
三、$parent $children
可以在组件中通过this.$parent,this.$children来获取父、子组件实例,并直接修改他们的data(不推荐)
四、.sync修饰符
以下摘自vue官方文档
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。
这也是为什么我们推荐以 update:myPropName
的模式触发事件取而代之。举个例子,在一个包含 title
prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:
this.$emit('update:title', newTitle)
然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。例如:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
为了方便起见,我们为这种模式提供一个缩写,即 .sync
修饰符:
<text-document v-bind:title.sync="doc.title"></text-document>
然后在子组件中通过this.$emit('update:titile')来触发事件
五、eventBus
eventBus其实就是一个 空的vue组件。基于订阅发布模式,组件通过$on注册事件,$emit触发事件,由eventBus进行调度
新建一个eventBus.js
import Vue from 'vue';
export const eventBus = new Vue();
// eventBus.js
在vue组件中引入eventBus A组件中触发事件changeNum B组件中注册事件changeNum
import {eventBus} from './eventBus.js';
// ... 省略
changeNum(){
eventBus.$emit('changeNum',this.num)
}
// A.vue
import {eventBus} from './eventBus.js';
// ... 省略
changeNum(){
eventBus.$on('changeNum',(num)=>{
this.num = num;
})
}
// B.vue
六 provide和inject
props只能在父子组件中传递,provide和inject相当于高级版的props
provider/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。
需要注意的是这里不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据。
七、vuex
不再赘述