在vue项目中,如果遇到跨组件多层次传值的话,一般会用到vuex,或者其他第三方共享状态管理模式,如pinia等,但是对于父组件与多层次孙子组件时,建议使用provide 与 inject,与之其他方式相比,简单方便。
基础使用
Vue2 option api
# App.vue
<template><parent/>
</template><script>import Parent from "@/components/parent.vue";export default {name: 'App',components: {Parent},provide: {word: 'Hello Word'}
}
</script># parent.vue
<template><child />
</template><script>
import Child from "@/components/child.vue";export default {name: "parent",components: {Child}
}#child.vue
<template><span>{{ word }}</span>
</template><script>
export default {name: "child",inject: ['word']
}
在界面就显示出相应内容。
inject 与 props 是相似,可以是一个数组也可以是一个对象,如果是对象的话,可以为每一个属性另设别名,默认值。如下
inject: {childWord: {from: 'word',default: '默认值'}}
childWord 是孙子组件另起的别名;from 数据来源字段;default 默认值,default 与 props 中的 default 一样,如果默认值是一个对象的话,default 值必须是一个工厂函数返回值。
Vue3 composition api
# App.vue
<template><parent />
</template><script setup>import Parent from "@/components/parent.vue";import {provide} from "vue";provide('word', 'Hello Vue3.0')
</script># chile.vue
<template>{{ word }}
</template><script setup>import { inject } from "vue";const word = inject('word');
</script>
inject 默认值
const word = inject('word', '默认值');
或者
const word = inject('word', () => {});
在 Vue3.0 中响应式数据传递,因为没有 this 所限制,可以直接传递 ref ,或 reactive 值,如下
let val = ref(0);
provide('word', val.value);
或者
provide('word', val)
对于 ref 数据有没有 .value 都可以,因为在 provide 中 会通过 isRef 函数去判断当前值是否为 ref 数据,如果是,Vue 会自动 通过 toValue 函数去取值。
注意
provide 与 inject 可以传递响应式数据,但是 provide 必须是一个函数返回值,与组件中的 data 一样,原因是,如果是一个普通的对象的话,this 指向的是 undefined ,不是该组件实例,这里是运用到的了闭包函数,使得this 指向当前组件实例。
# App.vueprovide: {context: this}# child.vueinject: ['context'],mounted() {console.log(this.context);}
这时控制台打印出来的 this 值是 undefined。
如果 provide 是一个函数的话,打印出来的就是当前实例对象。
provide 也不能是一个箭头函数,因为箭头函数还会改变 this 的指向。
provide: () => {return {context: this}}
这时 this 指向的也是 undefined。