序言:我们都知道vue父子组件通信主要通过props和事件,那还知道其他形式的通讯方式吗?本文将一一为你揭晓。
1、sync
修饰符 + this.$emit('update:属性名', data)
(父子组件)
1.1、sync修饰符的作用
在Vue中,子父组件最常用的通信方式就是通过props进行数据传递,props值只能在父组件中更新并传递给子组件,在子组件内部,是不允许改变传递进来的props值,这样做是为了保证数据单向流通。但有时候,我们会遇到一些场景,需要在子组件内部改变props属性值并更新到父组件中,这时就需要用到.sync修饰符。
如果我们在子组件中直接修改props中的属性值,将会报以下错误:
报错的大概意思就是:不允许直接修改props里面的属性值。
这里可以参考一篇文章:https://blog.csdn.net/XuM2222...
1.2、利用sync修饰符实现双向数据绑定
父组件:通过给绑定属性添加sync修饰符将值传递给子组件,父组件值改变,子组件随着改变。
子组件:通过this.$emit('update:属性名', data)来改变props属性值并更新父组件对应的值。
点击加一{{foo}}
2、自定义组件v-model+this.$emit('自定事件名', data)(父子组件)
2.1、v-model语法糖
2.2、自定义组件v-model
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
`
})
现在在这个组件上使用 v-model 的时候:
这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当
注意:你仍然需要在组件的 props 选项里声明 checked 这个 prop。
2.3、使用自定义组件v-model实现双向数据绑定
父组件:通过v-model向子组件传值,并监听自定义函数更新值。
子组件:通过model选项自定义绑定属性名和方法,使用$emit触发自定义方法更新父组件的值。
点击加一{{foo}}
运行结果:
3、value方式+this.$emit('input', data)(父子组件)
这种方式实现双向数据绑定是基于v-model语法糖
点击加一{{foo}}
4、props + $emit
(父子组件)
props + $emit
5、$attrs + $listeners
(祖孙组件)
上面这种组件通信的方式只适合直接的父子组件,也就是如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A直接想传递数据给组件C那就行不通了! 只能是组件A通过 props 将数据传给组件B,然后组件B获取到组件A 传递过来的数据后再通过 props 将数据传给组件C。当然这种方式是非常复杂的,无关组件中的逻辑业务一种增多了,代码维护也没变得困难,再加上如果嵌套的层级越多逻辑也复杂,无关代码越多!
针对这样一个问题,Vue 2.4
提供了$attrs
和 $listeners
来实现能够直接让组件A传递消息给组件C。
$attrs + $listeners
将 $attrs
和 $listeners
单独拿出来说说吧!
-
$attrs
:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class
和style
除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定属性 (class和style
除外),并且可以通过v-bind="$attrs"
传入内部组件。 -
$listeners
:包含了父作用域中的 (不含.native
修饰器的)v-on
事件监听器。它可以通过v-on="$listeners"
传入内部组件。
6、中央事件总线 EventBus
(父子、祖孙、兄弟组件)
对于两个组件不是父子关系,那么又该如何实现通信呢?在项目规模不大的情况下,完全可以使用中央事件总线EventBus
的方式。如果你的项目规模是大中型的,那你可以使用我们后面即将介绍的Vuex 状态管理。
EventBus
通过新建一个Vue
事件bus
对象,然后通过bus.$emit
触发事件,bus.$on
监听触发的事件。
事件总线eventBus
7、provide + inject
(父子、祖孙)
关于provide/inject介绍:https://segmentfault.com/a/11...
熟悉 React 开发的同学对 Context API
肯定不会陌生吧!在 Vue 中也提供了类似的 API 用于组件之间的通信。
在父组件中通过 provider
来提供属性,然后在子组件中通过 inject 来注入变量。不论子组件有多深,只要调用了 inject
那么就可以注入在 provider 中提供的数据,而不是局限于只能从当前父组件的 prop 属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。这和 React 中的 Context API
有没有很相似!
⚠️ 注意:官网文档提及 provide 和 inject 主要为高阶插件/组件库提供用例(比如elementui),并不推荐直接用于应用程序代码中。
provide + inject
8、$parent + $children
这里要说的这种方式就比较直观了,直接操作父子组件的实例。$parent
就是父组件的实例对象,而$children
就是当前实例的直接子组件实例了,不过这个属性值是数组类型的,且并不保证顺序,也不是响应式的。
$parent + $children
9、ref
ref
参考:
https://blog.csdn.net/songxiu...
https://juejin.im/post/5c77c4...