通过provide与inject进行组件传值
provide与inject的功能是可以把一个祖先组件指定的数据和方法,传递给其所有子孙组件中。 主要在开发高阶插件/组件库时使用, 官网不建议在普通应用程序中直接使用该办法,因为存在管不好的情况。
provide/inject用法
provide/inject:在父级组件中通过provide来提供变量,然后在子级组件中通过inject来注入变量,这里不论子级组件有多深,只要调用了inject那么就可以获取父级组件中provide注入的数据。
语法
provide:是一个对象,或者是一个返回对象的函数。对象中包含要给子孙后代的数据,也就是属性和属性值。
父组件通过provide将自己的数据以对象形式传出去
//对象形式
provide: {
message: 'provided by father'
}
//返回对象的函数形式
provide(){
return {
message: ()=>{ return this.msg}
}
}
inject:一个字符串数组,或者是一个对象。对象的属性名是子组件中使用的绑定名,对象属性值包含from和default默认值。from是在可用的注入内容中搜索用的 key (字符串或 Symbol),意思就是祖父多层provide提供了很多数据,from属性指定取哪一个key;default指定默认值。
子孙组件:使用注入的属性名作为数据入口接收属性值
//字符串数组
inject:['message']
//对象
inject:{
// 使用一个默认值使其变成可选项
msg: { // 键名
from: 'message', // 来源
default: '' // 默认值
}
其代码执行顺序是:data->provide->created->mounted
ps:provide 和 inject 绑定并不是可响应的。 即如果在父级组件中改变了传入的数据以后,子级组件并不会得到改变后的值,也就是此时父级组件和子级组件的数据出现了不一致的情况,所以需要人为的设计将数据改为响应式的数据。
当传入的是一个可监听的对象,那么其对象的属性还是可响应的。 也就是当传入的数据是一个字符串,基本数据类型是不可响应的。而当函数返回一个对象,该对象保存了父组件data参数中的数据。此时,数据就可响应了,在父级组件修改了数据,传给子级组件的数据也会被修改,子级组件就要通过调用函数得到传入的数据。
//父级组件
data(){
return {
message: "aa"
}
}
provide(){
return {
msg:()=>this.message
}
}
//子级组件
<div> 信息:{{msg()}} </div>
<div> 信息:{{foo()}} </div>
inject:['msg']
或者
inject: {
foo: {
from: 'bar',
default: () => [1, 2, 3]
}
}
基础用法: 传个字符串(数据不是可响应的)
//爷爷组件
<template>
<div id="app">
<h1>app组件----{{ msg }}</h1>
<button @click="msg='app组件数据被修改'">点击修改值</button>
<two></two>
</div>
</template>
<script>
import Two from "@/components/Two.vue";
export default {
data() {
return {
msg: "app组件的数据",
};
},
components: {
Two,
},
provide:{
msg:"app组件的数据"
}
};
</script>
<style lang="scss">
#app {
width: 700px;
height: 700px;
background-color: goldenrod;
}
</style>
//爸爸组件
<template>
<div class="two">
<h1>two组件---{{msg}}</h1>
<three></three>
</div>
</template>
<script>
import three from "@/components/three.vue";
export default {
components:{
three
},
inject:["msg"]
}
</script>
<style lang="scss" scoped="scoped">
.two{
width: 500px;
height: 500px;
background-color: rgb(7, 251, 251);
}
</style>
//孙子组件
<template>
<div class="three">
<h1>three组件---{{msg}}</h1>
</div>
</template>
<script>
export default {
inject:["msg"]
}
</script>
<style lang="scss" scoped="scoped">
.three{
background-color: purple;
width: 400px;
height: 300px;
}
</style>
设计成响应式的数据
//父级组件
<template>
<div id="app">
<h1>app组件----{{ msg }}</h1>
<button @click="msg='app组件数据被修改'">点击修改值</button>
<two></two>
</div>
</template>
<script>
import Two from "@/components/Two.vue";
export default {
data() {
return {
msg: "app组件的数据",
};
},
components: {
Two,
},
provide(){
return {
message:()=>{
return this.msg;
}
}
}
};
</script>
<style lang="scss">
#app {
width: 700px;
height: 700px;
background-color: goldenrod;
}
</style>
//子级组件
<template>
<div class="two">
<h1>two组件---{{message()}}</h1>
<three></three>
</div>
</template>
<script>
import three from "@/components/three.vue";
export default {
components:{
three
},
computed:{
},
inject:['message']
}
</script>
<style lang="scss" scoped="scoped">
.two{
width: 500px;
height: 500px;
background-color: rgb(7, 251, 251);
}
</style>