Vue3+TS 中使用Provide/Inject 的例子
Vue3+TS 中使用Provide/Inject 的例子
·
详见:Provide / Inject | Vue.js (vuejs.org)
作用:在深度嵌套的组件中,将 prop 沿着组件链逐级传递会很麻烦。使用 Provide/Inject可以直接将父组件的数据传递给子孙组件
自己总结的,有不足或错误的地方,欢迎各位大佬指正
示例1:提供静态数据并提供默认值
father.vue
<script lang="ts">
import { defineComponent, provide } from 'vue'
import Son from './Son.vue'
export default defineComponent({
components: { Son },
setup() {
//provide 函数允许你通过两个参数定义 property:name (<String> 类型)和 value
provide('staticData', 'static') //提供无响应性的数据,该值不可以被子组件修改
},
})
</script>
son.vue
<script lang="ts">
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup() {
//inject(name,default) 函数有两个参数:要inject 的 property 的 name和默认值 (可选)
const staticData = inject('staticData','defaultValue')
return {
staticData,
}
},
})
</script>
示例2:直接提供响应式数据(不安全)
father.vue
<script lang="ts">
import { defineComponent, provide, ref } from 'vue'
import Son from './Son.vue'
export default defineComponent({
components: { Son },
setup() {
const reactivityData = ref('响应式数据')//ref或者reactive都可以
provide('reactivityData', reactivityData) //提供响应性的数据,该值可以被子组件修改。
},
})
</script>
son.vue
<script lang="ts">
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup() {
const reactivityData = inject('reactivityData')
return {
reactivityData,
}
},
})
</script>
示例3:使用readonly,使子组件无法直接修改父组件数据(即使是对象下的属性,也不能直接修改),但是可以由父组件provide一个方法以供子组件修改
father.vue
<script lang="ts">
import { defineComponent, provide, ref, readonly } from 'vue'
import Son from './Son.vue'
export default defineComponent({
components: { Son },
setup() {
const reactivityReadonlyData = ref({ name: '张三' })
provide('reactivityReadonlyData', readonly(reactivityReadonlyData)) //使用readonly,提供响应性的数据,该值可以不可以直接被子组件修改。但是可以再提供一个方法专门用于修改数据
const changeReactivityReadonlyData = (val: string) => {
reactivityReadonlyData.value.name = val
}
provide('changeReactivityReadonlyData', changeReactivityReadonlyData)
},
})
</script>
son.vue
<script lang="ts">
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup() {
const reactivityReadonlyData = inject('reactivityReadonlyData')
const changeReactivityReadonlyData = inject('changeReactivityReadonlyData')
return {
reactivityReadonlyData,
changeReactivityReadonlyData,
}
},
})
</script>
<template>
<div>子组件{{ reactivityReadonlyData.name }}</div>
<button @click="changeReactivityReadonlyData('李四')">点击修改</button>
</template>
示例4:推荐用法(安全,无报错)。最好给inject提供默认值
father.vue
<script lang="ts">
import { defineComponent, provide, Ref, ref, readonly, InjectionKey } from 'vue'
import Son from './Son.vue'
// 用户信息
export type UserInfoType = Ref<{
userName: string
userId: number
}>
//修改用户名
export type ChangeUserNameType = (val: string) => void
//Vue 提供了一个 InjectionKey 接口,该接口是扩展了 Symbol 的泛型类型。它可用于在生产者和消费者之间同步 inject 值的类型:
export const UserInfoKey: InjectionKey<UserInfoType> = Symbol()
export const ChangeUserNameKey: InjectionKey<ChangeUserNameType> = Symbol()
export default defineComponent({
components: { Son },
setup() {
const userInfo = ref({
userName: '静夜聆雨',
userId: 999,
})
const changeUserName = (val: string) => {
userInfo.value.userName = val
}
provide<UserInfoType>(UserInfoKey, readonly(userInfo))
provide<ChangeUserNameType>(ChangeUserNameKey, changeUserName)
},
})
</script>
<template>
父组件
<Son></Son>
</template>
son.vue
<script lang="ts">
import { defineComponent, inject, ref } from 'vue'
import { UserInfoKey, ChangeUserNameKey } from './Father.vue'
export default defineComponent({
setup() {
const userinfo = inject(
UserInfoKey,
ref({
userName: '',
userId: NaN,
})
)
const changeUserName = inject(ChangeUserNameKey, () => {
console.log('无法修改父组件的值')
})
return {
userinfo,
changeUserName,
}
},
})
</script>
<template>
子组件{{ userinfo.userName }}
<button @click="changeUserName('李四')">点击修改父组件</button>
</template>
更多推荐
已为社区贡献3条内容
所有评论(0)