一、概念解析
-
成对出现:provide和inject是成对出现的
-
作用:用于父组件向子孙组件传递数据
-
使用方法:provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据。
-
使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问父组件的数据
-
官网上说provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
-
provide:Object | () => Object(一个对象或返回一个对象的函数)
-
inject:Array<string> | { [key: string]: string | Symbol | Object }(一个字符串数组,或一个对象,对象的 key 是本地的绑定名)
provide和inject响应的例子:
// 父.vue
export default {
provide: {
title: 'Hello World'
}
}
// 子孙.vue
export default {
inject: ['title'],
mounted () {
console.log(this.title); //Hello World
}
}
列子:
用provide(提供)和inject(注入)来实现<router-view/>的现实隐藏可以做到局部刷新
1.在App.vue中使用provide
<div id="app">
<router-view v-if="isRouterAlive" />
</div>
export default {
provide(){
return{
reload:this.reload
}
},
data() {
return {
isRouterAlive:true
}
},
methods:{
reload(){
this.isRouterAlive=false
this.$nextTick(()=>{
this.isRouterAlive=true
})
}
}
};
2.在使用局部刷新的组件中使用inject
<script>
export default {
name: 'myComponent',
data () {
return {}
},
inject: ['reload'], //注入
methods: {
//调用这个方法就可以完美刷新了·
myCallBack(){
this.reload() //局部刷新
}
}
}
</script>
vue3写法
// App.vue
<template>
<router-view v-if="showPage"/>
</template>
<script lang="ts">
import { defineComponent, nextTick, provide, ref } from 'vue'
export default defineComponent({
setup () {
const showPage = ref<boolean>(true)
const onRefresh = () => {
showPage.value = false
nextTick(() => {
showPage.value = true
})
}
provide('reload', onRefresh)
return {
showPage
}
}
})
</script>
-
调用的页面
<script lang="ts">
import { defineComponent, inject } from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
setup () {
const store = useStore()
const onRefresh = inject<Function>('reload')
const handleClick = () => {
// 更新 Vuex
store.commit('setMatchUserId', 123)
// 刷新当前页面
onRefresh && onRefresh()
}
return {
handleClick
}
}
})
</script>