vue3中 provide/inject用法详解

依赖注入:provide 和 inject

什么情况下推荐provide/inject使用:Prop 多层级数据透传

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

在这里插入图片描述
上图方式,数据传递,只会一级一级的向下传递,如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况

provide 和 inject 可以帮助我们解决这一问题

一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖

在这里插入图片描述
Provide (提供)

provide() 函數接收兩個參數 provide(注入名,注入值)

<script setup>
import { provide } from 'vue'

provide(/* 注入名 */ 'message', /* 值 */ 'hello!')

//例子
provide('message', 'hello!')
</script>

第一個參數被稱為注入名,可以是一個字符串或是一個Symbol。後代組件會用注入名來查找期望注入的值。一个組件可以多次调用 provide(),使用不同的注入名,注入不同的依赖值。

第二個參數是提供的值,值可以是任意类型,包括响应式,比如一個 ref

import { ref, provide } from 'vue'

const count = ref(0)
provide('key', count)
provide全局注入
// main.ts页面
import { createApp } from 'vue'

const app = createApp({})

app.provide('message', 'hello!')  //全局注入一个message数据

//所有組件中都可以获取到注入的message数据
使用 Symbol 作注入名

什么情况下使用 Symbol 作为注入名:大型的应用,包含非常多的依赖提供,或者你正在编写提供給其他开发者使用的组件库

const myInjectionKey = Symbol()
provide(myInjectionKey, { /*要提供的数据*/ });

const injected = inject(myInjectionKey)

Inject (注入)

获取 provide注入数据的方法

<script setup>
import { inject } from 'vue'

const message = inject('message')

console.log('message', message)  //输出 hello!
</script>

注意:如果提供的值是一个 ref,注入进来的会是该 ref 对象,而不会自动解包为其內部的值(注入进来是什么类型,接收的就是什么类型)

inject 设置接收默认值

//如果注入的message为空的话 value会是默认的值  XXXXXX
const value = inject('message', 'XXXXXX')

在一些场景中,默认值可能需要通过调用一个函数或初始化一个类来取得

const value = inject('key', () => new ExpensiveClass(), true)

//第三个参数表示默认值应该被当作一个工厂函数

配合响应式数据使用

当提供 / 注入响应式的数据时,建议尽可能將任何对响应式状态的变更都保持在提供方組件中

<!-- 在供給方組件/父组件內 -->
import { provide, ref } from 'vue'

const location = ref('North Pole')

function updateLocation() {
  location.value = 'South Pole'
}

provide('location', {
  location,
  updateLocation
})
<!-- 在注入方組件/子组件内 -->
<script setup>
import { inject } from 'vue'

const { location, updateLocation } = inject('location')
</script>

<template>
   // 点击 updateLocation方法,可以调用父组件的updateLocation方法,从而更改 location 的值
  <button @click="updateLocation">{{ location }}</button>
</template>

如果你想确保提供的数据不能被(注入方组件/子组件)修改,可以使用 readonly() 来包裝提供的值

// readonly() 只读
const count = ref(0)

provide('read-only-count', readonly(count))

具体参考: https://zh-hk.vuejs.org/guide/components/provide-inject.html#prop-drilling

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值