1.props和$emit
父组件向子组件传递数据是通过props传递的(props写在子组件中),prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。
子组件传递数据给父组件是通过$emit触发事件,父组件通过v-on来监听并接收事件。
2.$attrs和$listeners
第一种方式处理父子组件之间的数据传输有一个问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢? 如果采用第一种方法,我们必须让组件A通过prop传递消息给组件B,组件B在通过prop传递消息给组件C;要是组件A和组件C之间有更多的组件,那采用这种方式就很复杂了。Vue 2.4开始提供了$attrs和$listeners来解决这个问题,能够让组件A之间传递消息给组件C。
$attrs:包含了父作用域中不作为 prop
被识别 (且获取) 的特性绑定 (class
和 style
除外)。当一个组件没有声明任何prop
时,这里会包含所有父作用域的绑定 (class
和 style
除外),并且可以通过 v-bind="$attrs"
传入内部组件——在创建高级别的组件时非常有用。
简单点讲就是包含了所有父组件在子组件上设置的属性(除了prop
传递的属性、class
和 style
)。
$listeners:包含了父作用域中的 (不含 .native
修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
简单点讲它是一个对象,里面包含了作用在这个组件上所有的监听器(监听事件),可以通过 v-on="$listeners"
将事件监听指向这个组件内的子元素(包括内部的子组件)。
3. 中央事件总线
上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。申明一个独立的空vue实例,即新建一个Vue事件bus对象,一般就写在mian.js中,然后通过bus.$emit触发事件,bus.$on监听触发的事件。
4. provide和inject
在 Vue.js 的 2.2.0+
版本中添加加了 provide 和 inject 选项。他们成对出现,用于父级组件向下传递数据。父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
5. $parent和$children
在组件内部可以直接通过子组件$parent对父组件进行操作,父组件通过$children对子组件进行操作。$children 的值是数组,而$parent是个对象。
6.ref / refs
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据。
7. vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上。
Vuex各个模块
- state:用于数据的存储,是store中的唯一数据源
- getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
- mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
- actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
- modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护
总结
常见使用场景可以分为三类:
- 父子组件通信: props; $parent / $children; provide / inject ; ref /refs; $attrs / $listeners
- 兄弟组件通信: eventBus ; vuex
- 跨级通信: eventBus;vuex;provide / inject 、$attrs / $listeners