Skip to content
文章目录

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' })
}