vue 朝花夕拾系列(7)- 组件通信provide/inject

vue 朝花夕拾系列(7)主要收录的就是vue组件间通信的几种方式,如
1.props、$emit/$on
2.vuex
3.$parent/$children
4.$refs
5.$root
6.$attrs/$listeners
7.provide/inject
8.中央事件bus(eventBus)
9.路由传参

本文主要阐述第七种:通过provide/inject实现祖先组件数据可以被后代组件共享的方式实现数据通信…

provide/inject(provide可以接受Object|()=>{})

  • Vue2.2.0新增API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系

  • 需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的—-vue官方文档 所以,上面 father.vue 的 userName 如果改变了,child.vue 的 this.name 是不会改变的,仍然是 pis。

基本核心用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// father.vue
export default {
provide: {
name: this.userName
},
data(){
return{
userName:'pis'
}
},
mounted(){
this.userName = "uncle" // 父组件改了userName,但是传给子孙组件inject还是pis
}
}
// child.vue
export default {
inject: ['name'],
mounted () {
console.log(this.name); // pis
}
}

provide与inject 怎么实现数据响应式

provide祖先组件的实例,然后在子孙组件中注入依赖,这样就可以在子孙组件中直接修改祖先组件的实例的属性,不过这种方法有个缺点就是这个实例上挂载很多没有必要的东西比如props,methods

使用2.6最新API Vue.observable 优化响应式 provide(推荐)

  • provide父组件的this实例对象(有多余没有用的参数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    // father 组件
    <div>
    <h1>fahter 组件</h1>
    <button @click="() => changeColor()">改变color</button>
    <ChildrenB />
    <ChildrenC />
    provide父组件的color:{{color}}
    </div>
    ......
    data() {
    return {
    color: "blue"
    };
    },
    // provide() {
    // return {
    // theme: {
    // color: this.color //这种方式绑定的数据并不是可响应的
    // } // 即father组件的color变化后,组件childrenB,childrenC不会跟着变
    // };
    // },
    provide() {
    return {
    theme: this//方法一:提供祖先组件的实例
    };
    },
    methods: {
    changeColor(color) {
    if (color) {
    this.color = color;
    } else {
    this.color = this.color === "blue" ? "red" : "blue";
    }
    }
    }
  • 使用新特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 方法二:使用2.6最新API Vue.observable 优化响应式 provide
provide() {
const provideData= Vue.observable({
color: this.$data // 使用observable包装后就动态响应式
});
return {
theme: provideData.color // 这样就可以监听到数据的变化了
};
},
methods: {
changeColor(color) {
if (color) {
this.theme.color = color;
} else {
this.theme.color = this.theme.color === "blue" ? "red" : "blue";
}
}
}
  • ComponentB或者ComponentC的组件中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    //  子孙组件中使用
<template functional>
<div class="border2">
<h3 :style="{ color:theme.color }">ComponentB或者ComponentC的组件中使用</h3>
</div>
</template>
<script>
export default {
inject:['theme'], // 引入父组件provide的this实例
inject: {
theme: {
//函数式组件取值不一样
default: () => ({})
}
}
};
</script>

参考链接

Vue 组件间通信六种方式
Vue 开发必须知道的 36 个技巧

初到贵宝地,有钱的给个钱场,没钱的挤一挤给个钱场