本篇主要讲述Vue2中组件间通信。目前 Vue 最新版本为。
props与自定义事件
这是Vue推荐使用的通信方法
Vue中通过props属性可以实现父组件向子组件的参数传递。
所有的 prop 都使得其父子之间形成了一个 单向下行绑定 :父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。
在子组件中定义props属性1
2
3
4
5Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
在父组件中传入对应的props属性1
2<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
Vue中通过自定义事件可以实现子组件向父组件的参数传递。
在子组件中触发事件1
this.$emit('myEvent', data)
在父组件中接受事件并进行处理1
<my-component v-on:my-event="doSomething"></my-component>
provide与inject
2.2.0+ 新增
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代组件注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。祖先组件中通过provide来提供变量,然后在子孙后代组件中通过inject来注入变量。不论子孙后代有多深,只要调用了inject那么就可以注入provide中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在祖先组件的生命周期内,子孙后代组件都可以调用。
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
1 | Vue.component('child', { |
props与.sync
2.3.0+ 新增
.sync 是一个自定义事件修饰符,可以实现对props的“双向绑定”
实际上sync只是props&自定义事件的一个语法糖
1 | <text-document v-bind:title.sync="doc.title"></text-document> |
实际上是以下写法的一个缩写
父组件1
2
3
4<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
子组件1
this.$emit('update:title', newTitle)
v-model
一个组件上的 v-model
默认会利用名为 value 的 prop 和名为 input 的事件
所以可以在父组件中使用 v-model="message"
然后在子组件中通过 $emit('input', newMessage)
来改变父组件上v-model绑定的值message。
但是像单选框、复选框等类型的输入控件可能会将 value
特性用于不同的目的。
$parent与$children/$refs
不推荐使用
在子组件中可以直接通过 this.$parent.$data
来访问和修改父组件的值,
在父组件中也可以通过 this.$children[0].$data
来访问和修改子组件的值
也可以在引用子组件时通过添加ref来使得父组件中可以通过 this.$refs.child.$data
来访问和修改子组件的值
$attr与$listener
2.4.0+新增
$attr与$listener实现了一种跨父子的参数传递方法
$attr包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件。
$listener包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件
1 | Vue.component('C', { |
Event Bus 中央事件总栈 $emit $on
为了实现非父子间的通信,我们可以通过通过使用一个空的Vue实例作为中央事件总栈来处理所有的事件,通过Vue自带的$emit $on来进行组件间通信。
1 | let bus = new Vue() |
甚至可以用app.js中的Vue实例来处理
1 | /* app.js*/ |
这样在组件中我们就可以通过以下方式处理
1 | this.bus.$emit('some-event', data) |