vue2中非父子组件的传值主要是通过事件总线,创建一个vue实例,通过在不同的组件中导入该实例来实现非父子组件之间的通信行为。
vue3提供了**provide**和**inject**属性,可以实现非父子组件之间的通信;
假设有三个组件:App.vue(父级)、sub1(子级)、sub2(子级的子级):
App.vue
<template>
<div style="border: 1px solid pink">
<h1>我是你爹</h1>
<span>👇</span>
<sub1/>
</div>
</template>
<script>
import sub1 from './sub1'
export default {
name: "App",
components:{
sub1,
},
provide:{
names:['peanut','javascriptKing']
}
}
</script>
<style scoped>
</style>
sub1.vue
<template>
<h2>我是一级子组件</h2>
<span>👇</span>
<sub2/>
</template>
<script>
import sub2 from "./sub2";
export default {
name: "sub1",
components:{
sub2,
}
}
</script>
<style scoped>
</style>
sub2.vue
<template>
<h3>我是最小的,也就是孙子</h3>
<div>我引用了顶级组件的names数组 ===> {{names}}</div>
</template>
<script>
export default {
name: "sub2",
inject:['names'],
}
</script>
<style scoped>
</style>
实现效果如下,可以看到是可以正常获取顶级组件中传递的值:
但是也会出现问题: 就是顶级组件要传递的值变化时,如何让它实现响应式呢? 如何在provide属性中通过this获取当前的实例呢?
这里就需要将provide属性书写为方法的形式,返回一个数组或者对象:
<template>
<div style="border: 1px solid pink">
<h1>我是你爹</h1>
<span>👇</span>
<sub1/>
</div>
</template>
<script>
import sub1 from './sub1'
export default {
name: "App",
data(){
return {
names:['peanut','javascriptKing']
}
},
components:{
sub1,
},
provide(){
return {
names:this.names
}
}
}
</script>
<style scoped>
</style>
像上面这样写,虽然可以拿到this指向的实例下的数据,但是如何让它们形成依赖关系,实现响应式呢?对此我们需要对App.vue做如下的修改:
<template>
<div style="border: 1px solid pink">
<h1>我是你爹</h1>
<span>👇</span>
<sub1/>
</div>
</template>
<script>
import sub1 from './sub1'
import { computed } from 'vue'
export default {
name: "App",
data(){
return {
names:['peanut','javascriptKing']
}
},
components:{
sub1,
},
provide(){
return {
names:computed(() =>{ this.names.length })
}
},
mounted() {
setInterval(()=>{
this.names.push('vue大王!')
},1000)
}
}
</script>
<style scoped>
</style>
|