provide和inject
作用
解决数据透传问题,让子孙组件都可以直接访问先辈组件 provide 的数据
用法
基本使用
html
<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'
const location = ref('North Pole')
function updateLocation() {
location.value = 'South Pole'
}
// 供给方提供修改注入数据的方法,让注入方只能通过该方法修改数据
provide('location', {
location,
updateLocation,
})
</script>
html
<!-- 在注入方组件 -->
<script setup>
import { inject } from 'vue'
// 注入方获取供给方提供的数据,修改供给方提供的数据,也使用供给方提供的修改方法
const { location, updateLocation } = inject('location')
</script>
<template>
<button @click="updateLocation">{{ location }}</button>
</template>
如果某个数据不希望被注入方修改
html
<script setup>
import { ref, provide, readonly } from 'vue'
const count = ref(0)
provide('read-only-count', readonly(count))
</script>
注入默认值
js
// 如果没有祖先组件提供 "message"
// `value` 会是 "这是默认值"
const value = inject('message', '这是默认值')
在一些场景中,默认值可能需要通过调用一个函数或初始化一个类来取得。为了避免在用不到默认值的情况下进行不必要的计算或产生副作用,我们可以使用工厂函数来创建默认值:
js
const value = inject('key', () => new ExpensiveClass())
避免变量名冲突
普通数据
js
// keys.js
import type { InjectionKey } from 'vue'
export const myInjectionKey = Symbol() as InjectionKey<string>
js
// 在供给方组件中
import { provide } from 'vue'
import { myInjectionKey } from './keys.js'
provide(myInjectionKey, {
/*
要提供的数据
*/
})
js
// 注入方组件
import { inject } from 'vue'
import { myInjectionKey } from './keys.js'
const injected = inject(myInjectionKey)
响应式数据
ts
import { InjectionKey, Ref } from 'vue'
export interface Params {
name: string
}
export const paramsKey: InjectionKey<Ref<Params>> = Symbol('')
export type setParams = (params: Params) => void
export const setParamsKey: InjectionKey<setParams> = Symbol('')
ts
// 在供给方组件中
import { paramsKey, setParamsKey, Params } from './type'
const user = ref({ name: 'zs' })
provide(paramsKey, user)
function setUser(params: Params) {
user.value.name = params.name
}
provide(setParamsKey, setUser)
ts
// 注入方组件
import { inject } from 'vue'
import { paramsKey, setParamsKey } from './type'
const user = inject(paramsKey)
const setUser = inject(setParamsKey)
console.log('user', user)
function handleClick() {
setUser?.({ name: 'ls' })
}