vue 组件之间的通信

目录

前言

一、props 和 $emit

1、一般的通信

2、子组件更新父组件的变量

二、$attrs 和 $listeners

三、eventBus——$emit 和 $on

四、provide 和 inject(跨组件通信)

1、认识 provide 和 inject

2、provide 和 inject 的使用

(1)、传递普通的数据

 (2)、传递异步的数据

五、使用 vue-ref 插件结合 provide 和 inject 获取组件的实例

六、v-model

七、$parent、$children 和 $refs

1、$children 和 $rfes

2、$parent(不建议使用)

3、案例

八、vuex 处理组件之间的数据交互


前言

参考:vue组件之间8种组件通信方式总结

vue 组件之间的通信方式大概有 9 种:

  • props 和 $emit
  • $refs
  • $attrs 和 $listeners
  • eventBus
  • provide 和 inject
  • v-model
  • $parent 和 $children
  • boradcast 和 dispatch
  • vuex 处理组件之间的数据交互

一、props 和 $emit

父传子——props

子传父——$emit

1、一般的通信

Vue.component("child", {
    data() {
        return {
            mymessage: this.message,
        };
    },
    template: `
        
`, props: ["message"], //得到父组件传递过来的数据 methods: { passData(val) { //触发父组件中的事件 this.$emit("getChildData", val); }, }, }); Vue.component("parent", { template: `

this is parent compoent!

`, data() { return { message: "hello", }; }, methods: { //执行子组件触发的事件 getChildData(val) { console.log(val); }, }, }); var app = new Vue({ el: "#app", template: `
`, });

上述代码中,父组件传递了message数据给子组件,并且通过v-on绑定了一个getChildData事件来监听子组件的触发事件;子组件通过props得到相关的message数据,最后通过this.$emit触发了getChildData事件。

假设有这么一个场景:私人订制一只宠物。父组件是具有定制宠物的给用户的功能,子组件具有决定定制什么宠物的功能。那么此时,子组件在调用父组件的定制宠物的给用户的功能时,就需要给选定一种宠物,这就需要传递第二个参数了。

2、子组件更新父组件的变量

vue 在子组件中更新父组件中传过来的变量——.sync 和 $emit(update:xxx)icon-default.png?t=N7T8https://blog.csdn.net/mChales_Liu/article/details/122193214

二、$attrs 和 $listeners

问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢?

可以借助 $attrs 和 $listeners 来实现 “隔代传值”。

Vue.component("C", {
    template: `
        
`, methods: { passCData(val) { //触发父组件A中的事件 this.$emit("getCData", val); }, }, }); Vue.component("B", { data() { return { mymessage: this.message, }; }, template: `
`, props: ["message"], //得到父组件传递过来的数据 methods: { passData(val) { //触发父组件中的事件 this.$emit("getChildData", val); }, }, }); Vue.component("A", { template: `

this is parent compoent!

`, data() { return { message: "hello", messagec: "hello c", //传递给c组件的数据 }; }, methods: { getChildData(val) { console.log("这是来自B组件的数据"); }, //执行C子组件触发的事件 getCData(val) { console.log("这是来自C组件的数据:" + val); }, }, }); var app = new Vue({ el: "#app", template: `
`, });

三、eventBus——$emit 和 $on

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。

$emit 和 $on 的实现:新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。

Vue.component("brother1", {
    data() {
        return {
            mymessage: "hello brother1",
        };
    },
    template: `
        

this is brother1 compoent!

`, methods: { passData(val) { //触发全局事件globalEvent bus.$emit("globalEvent", val); }, }, }); Vue.component("brother2", { template: `

this is brother2 compoent!

brother1传递过来的数据:{{brothermessage}}

`, data() { return { mymessage: "hello brother2", brothermessage: "", }; }, mounted() { //绑定全局事件globalEvent bus.$on("globalEvent", (val) => { this.brothermessage = val; }); }, }); //中央事件总线 var bus = new Vue(); var app = new Vue({ el: "#app", template: `
`, });

四、provide 和 inject(跨组件通信)

provide 和 inject 是成对出现的。在上层组件中通过 provide 来提供变量,然后在下层组件中通过 inject 来注入变量。用于父组件向子孙组件传递数据。

1、认识 provide 和 inject

provide 选项可以是:

  • 一个对象。
  • 一个函数,该函数的返回值是一个对象。

inject 选项可以是:

  • 一个字符串数组。
  • 一个对象。此时:
    • 对象的 key 是当前组件将要使用的变量名。
    • 对象的 value 可以是:
      • provide 里提供的属性,以及。
      • 一个对象,该对象包括两个属性:
        • from 属性:provide 里提供的属性。
        • default 属性:默认值。

provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

2、provide 和 inject 的使用

(1)、传递普通的数据

父组件:


子组件:


 (2)、传递异步的数据

父组件:


子组件:



【注意】小型状态管理,可以使用 provide/inject。大型状态管理,建议使用 vuex。

 【扩展】 

vue中的provide和inject

vue中provide和inject使用

五、使用 vue-ref 插件结合 provide 和 inject 获取组件的实例

可以使用 ref 来获取跨级组件实例。

安装:vue-ref

npm i vue-ref -S

然后,在main.js中写入下面的代码:

import ref from 'vue-ref';
Vue.use(ref, { name: 'getRef' });// 这里之所以重命名,是为了避免与vue预留的v-ref指令冲突

 假设,已经创建了vue实例,并且在其中引入了index.vue,或者配置好了vue-router。

// index.vue

 子组件:A

// ChildrenA1.vue

子组件的子组件:E

// childrenE.vue

 子组件的子组件:H

六、v-model

父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input’,val)自动修改v-model绑定的值。

Vue.component("child", {
    props: {
        value: String, //v-model会自动传递一个字段为value的prop属性
    },
    data() {
        return {
            mymessage: this.value,
        };
    },
    methods: {
        changeValue() {
            this.$emit("input", this.mymessage); //通过如此调用可以改变父组件上v-model绑定的值
        },
    },
    template: `
        
`, }); Vue.component("parent", { template: `

this is parent compoent!

{{message}}

`, data() { return { message: "hello", }; }, }); var app = new Vue({ el: "#app", template: `
`, });

注意:在组件上使用 v-model

七、$parent、$children 和 $refs

有时候我们需要父组件直接访问子组件、子组件直接访问父组件,或者子组件访问根组件:

  • 父组件访问子组件:使用 $children 或 $refs
  • 子组件访问父组件:使用 $parent

1、$children 和 $rfes

this.$children 是一个数组类型,它包含了所有子组件对象,可以通过循环它拿到所有子组件数据。

比如:this.$children[2] 来拿到第三个子组件的数据。
但是这么做有一个问题:比如开发时突然在这三个子组件中又插入了一个子组件(可能相同,也可能不同),这时候 this.$children[2] 就不再是我们需要的了。怎么办呢?使用 $rfes。

2、$parent(不建议使用)

$parent 是当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。该属性只读。

不建议使用 $parent,因为它的耦合度很高,容易发生一些错误。

3、案例

Vue.component("child", {
    props: {
        value: String, //v-model会自动传递一个字段为value的prop属性
    },
    data() {
        return {
            mymessage: this.value,
        };
    },
    methods: {
        changeValue() {
            this.$parent.message = this.mymessage; //通过如此调用可以改变父组件的值
        },
    },
    template: `
        
`, }); Vue.component("parent", { template: `

this is parent compoent!

`, methods: { changeChildValue() { this.$children[0].mymessage = "hello"; }, }, data() { return { message: "hello", }; }, }); var app = new Vue({ el: "#app", template: `
`, });

八、vuex 处理组件之间的数据交互

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。


详情可参考:Vuex

你可能感兴趣的:(#,Vue.js,vue.js,javascript)