这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深
provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。
inject 选项应该是:
一个字符串数组
举例
需求
一键换肤:点击一个按钮,整个页面的按钮和文字颜色变化。
结构
我们采用一个三层嵌套的组件。
最上层是App.vue,它包含五个Child组件。
第二层是Child1.vue(2/3/4/5),它包含一段文本Child1,和切换颜色组件。
第三层是ChangeThemeButton.vue,它只有一个“换肤”按钮。
App.vue
通过类名的改变,切换颜色。data里有一个 themeName 数据,默认是 blue 。当变为 red 时,通过CSS样式变成红色。
<template>
<div :class="`app theme-${themeName}`">
<Child1/>
...
</div>
</template>
<script>
import Child1 from "./components/Child1.vue";
...
export default {
name: "App",
data() {
return {
themeName: "blue", // 'red'
fontSize: "normal" // 'big' | 'small'
};
},
components: {
Child1,
...
}
};
</script>
Child1.vue
<template>
<div>Child 1
<change-theme-button/>
</div>
</template>
<script>
import ChangeThemeButton from "./ChangeThemeButton.vue";
export default {
components: {
ChangeThemeButton
}
};
</script>
ChangeThemeButton.vue
<template>
<div>
<button>换肤</button>
</div>
</template>
我们需要在第三层组件里改变最上层组件的一个data。
需要用到 provide ,在最上层组件里把需要用到的数据提供出来。即 themeName
//App.vue
provide(){
return {
themeName:this.themeName,
changeTheme:this.changeTheme,
}
},
methods:{
changeTheme(){
if(this.themeName==='blue'){
this.themeName='red'
}else{
this.themeName='blue'
}
}
},
因为this.themeName是一个字符串,所以提供出去的themeName是原本字符串的复制品。即,如果在其他地方修改themeName,是不会影响原本的数据的
所以在按钮组件里,注入这个变量后,不能点击按钮直接修改 this.themeName。
那怎么办呢?
在你这里修改不好使,那我(App.vue)在我自己身上写一个函数,修改我自己的数据,然后把这个函数提供给你,你注入这个函数,就可以使用了。
//ChangeThemeButton.vue
<template>
<div>
<button @click='x'>换肤</button>
</div>
</template>
<script>
export default {
inject:['themeName','changeTheme'],
methods:{
x(){
this.changeTheme()
},
}
}
</script>
可以看到,provide/inject选项类似于祖先栽树,后人乘凉。
在最上边把我的方法,数据都提供好,下边的子孙们谁都可以用,谁想用就inject,注入到自己身上,就是this上。
作用:大范围的data和methods共用。
不能只传themeName,不传changeTheme方法。因为我提供出去的时候,themeName的值是被复制给provide的,和原来的不是同一个,所以改变复制出去的值,并不会影响原本的值。
也可以在定义这个data的时候,把字符串改成对象,提供出去的就是引用。所以在按钮组件里直接修改是可以改变原本的值的。但是不推荐这样做。容易失控
