vue组件通信进阶

序言:我们都知道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属性值并更新父组件对应的值。



结果运行:
vue组件通信进阶_第1张图片

2、自定义组件v-model+this.$emit('自定事件名', data)(父子组件)

2.1、v-model语法糖

vue组件通信进阶_第2张图片

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。同时当 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

注意:你仍然需要在组件的 props 选项里声明 checked 这个 prop。

2.3、使用自定义组件v-model实现双向数据绑定

父组件:通过v-model向子组件传值,并监听自定义函数更新值。
子组件:通过model选项自定义绑定属性名和方法,使用$emit触发自定义方法更新父组件的值。



运行结果:

vue组件通信进阶_第3张图片

3、value方式+this.$emit('input', data)(父子组件)

这种方式实现双向数据绑定是基于v-model语法糖



运行结果:
vue组件通信进阶_第4张图片

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 所识别 (且获取) 的特性绑定 (classstyle 除外)。当一个组件没有声明任何 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...

你可能感兴趣的:(组件通信,vue.js)