Vue组件通信方式全面详解

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Vue组件通信方式全面详解

小马哥&   2020-04-02 我要评论
## vue组件通信方式全面详解 众所周知,Vue主要思想就是组件化开发。因为,在实际的项目开发中,肯定会以组件的开发模式进行。形如页面和页面之间需要通信一样,Vue 组件和组件之间肯定也需要互通有无、共享状态。接下来,我们就悉数给大家展示所有 Vue 组件之间的通信方式。 ### 组件关系 ![](https://img2020.cnblogs.com/blog/1364810/202004/1364810-20200402100152682-587394401.png) - App组件和A组件、A组件和B组件、B组件和C组件形成父子关系 - B组件和D组件形成兄弟关系 - App组件和C组件、App和B组件形成了隔代关系(其中的层级可能是多级,既隔多代) ### 组件通信 ------ 这么多的组件关系,那么组件和组件之间又有哪些通信的方式呢?各种方式的区别又是什么?适用场景又是什么呢? #### props和$emit 这种方式是我们日常开发中应用最多的一种方式。 props以单向数据流的形式可以很好的完成父子组件的通信 所谓单向数据流:就是数据只能通过 props 由父组件流向子组件,而子组件并不能通过修改 props 传过来的数据修改父组件的相应状态。至于为什么这样做,Vue 官网做出了解释: **\*所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。* **额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。** 正因为这个特性,于是就有了对应的 `$emit`。`$emit` 用来触发当前实例上的事件。对此,我们可以在父组件自定义一个处理接受变化状态的逻辑,然后在子组件中如若相关的状态改变时,就触发父组件的逻辑处理事件。 ```js let Child = { template: `
`, props: ['msg'], methods: { handleClick() { this.$emit('getChildData', '子组件数据') } }, } let Parent = { data() { return { msg: '小马哥', val:'' } }, methods: { getChildData(val) { this.val = val; } }, template: `

我是一个父组件

我是{{val}}

`, components: { Child } } let vm = new Vue({ el: '#app', template: `
`, components: { Parent } }) ``` 1. **父传子**:父组件传递msg数据给子组件,通过v-bind绑定msg,子组件中直接可以用props接收绑定的数据 2. **子传父**:子组件触发相应的事件,通过$emit触发事件传递数据,父组件中绑定对应的事件,通过$on监听对应的事件 接收子组件传递的数据 #### EventBus-中央事件总线 如果想实现兄弟组件之间进行通信,在项目规模不大的情况下,完全可以使用中央事件总线`EventBus`的方式。如果你的项目规模是大中型的,那我们会使用`vuex状态管理` `EventBus`通过新建一个`Vue`事件`bus`对象,通过`bus.$emit`触发事件,bus.$on监听触发的事件。 ```js Vue.component('A', { template: `

我是A组件

`, data() { return { msg: 'hello 小马哥' } }, methods: { handleClick() { this.$bus.$emit('globalEvent',this.msg); } }, }) Vue.component('B', { template: `

我是B组件

{{aValue}}

`, data() { return { aValue: '' } }, created () { this.$bus.$on('globalEvent',(val)=>{ this.aValue = val; }) }, }) // 定义中央事件总线 let bus = new Vue(); // 将中央事件总线赋值给Vue.prototype中,这样所有组件都能访问到了 Vue.prototype.$bus = bus; let vm = new Vue({ el: '#app', template: `
`, }) ``` #### $attrs和$listeners 通过 `props`进行组件通信的方式只适合直接的父子组件,如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A直接想传递数据给组件C那就行不通了! 只能是组件A通过 props 将数据传给组件B,然后组件B获取到组件A 传递过来的数据后再通过 props 将数据传给组件C。当然这种方式是非常复杂的,无关组件中的逻辑业务一种增多了,代码维护也没变得困难,再加上如果嵌套的层级越多逻辑也复杂,无关代码越多! 针对这样一个问题,Vue 2.4提供了`$attrs` 和`$listeners`来实现能够直接让组件A传递消息给组件C ```js Vue.component('A', { template: `

我是A组件

`, methods: { getCData(val) { alert(val) } }, data() { return { msg: 'hello 小马哥' } }, }) Vue.component('B', { template: `

我是B组件

`, // props: ['msg'], data() { return { } } }) Vue.component('C', { template: `

我是C组件

{{$attrs.msg}}

`, methods: { handleClick() { this.$emit('getCData', 'C组件的数据') } }, data() { return { } } }) let vm = new Vue({ el: '#app', template: `
`, }) ``` - `$attrs`:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (`class` 和 `style` 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定属性 (class和 `style` 除外),并且可以通过 `v-bind="$attrs"` 传入内部组件。 - `$listeners`:包含了父作用域中的 (不含 `.native` 修饰器的) `v-on` 事件监听器。它可以通过 `v-on="$listeners"` 传入内部组件。 #### provide和inject 在父组件中通过 `provider` 来提供属性,然后在子组件中通过 inject 来注入变量。不论子组件有多深,只要调用了 `inject` 那么就可以注入在 provider 中提供的数据,而不是局限于只能从当前父组件的 prop 属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。这和 React 中的 `Context API` 有没有很相似! ```js Vue.component('A', { template: `

我是A组件

`, provide:{ a:"祖先A的数据" }, data() { return { msg: 'hello 小马哥' } }, }) Vue.component('B', { template: `

我是B组件

`, data() { return { } } }) Vue.component('C', { template: `

我是C组件

{{a}}

`, inject:['a'], data() { return { } } }) let vm = new Vue({ el: '#app', template: `
`, }) ``` - 在 `parent` 组件中,通过 `provide` 属性,以对象的形式向子孙组件暴露了一些属性 - 在 `child` 组件中,通过 `inject` 属性注入了 `parent` 组件提供的数据,实际这些通过 `inject` 注入的属性是挂载到 Vue 实例上的,所以在组件内部可以通过 this 来访问 > ⚠️ 注意:官网文档提及 provide 和 inject 主要为高阶插件/组件库提供用例,并不推荐直接用于应用程序代码中。 #### $parent和$children 这里要说的这种方式就比较直观了,直接操作父子组件的实例。`$parent` 就是父组件的实例对象,而 `$children` 就是当前实例的直接子组件实例了,不过这个属性值是数组类型的,且并不保证顺序,也不是响应式的。 ```js Vue.component('Parent', { template: `

我是父组件

{{msg}}
`, mounted () { //读取子组件数据,注意$children并不保证顺序,也不是响应式的 console.log(this.$children[0].a) }, data() { return { msg: 'hello 小马哥' } }, }) Vue.component('Child', { template: `

我是孩子组件

{{myMsg}}

`, methods: { changeValue() { this.$parent.msg = '子组件中的数据' } }, data() { return { myMsg:this.$parent.msg, a:"小马哥" } } }) let vm = new Vue({ el: '#app', template: `
`, }) ``` #### Vuex状态管理 Vuex 是状态管理工具,实现了项目状态的集中式管理。工具的实现借鉴了 [Flux](https://facebook.github.io/fluxhttps://img.qb5200.com/download-x/docs/overview.html)、[Redux](http://redux.js.org/)、和 [The Elm Architecture](https://guide.elm-lang.org/architecture/) 的模式和概念。当然与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。详细的关于 Vuex 的介绍,你既可以去查看[官网文档](https://vuex.vuejs.org/zh/),也可以查看本专栏关于 Vuex 一系列的介绍。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们