详解vue3中的依赖提供和注入

我们在父子关系的组件中提供数据时常常使用props,这种传递数据的方式有个确切的前提,就是两个组件的关系必须是父和子的关系。如果是祖父和孙子的关系,祖父和重孙的关系等等,数据只能通过props一层一层地往下传递,这个问题就是”prop 逐级透传“问题,显然这样是非常麻烦地,这种情况下传递数据就可以使用依赖注入了。

在Vue 3中,provideinject 是用于实现组件之间依赖注入的一对新的 API。这两个 API 允许你在祖先组件中提供数据,然后在后代组件中注入这些数据,实现了一种更灵活的组件通信方式。

provide提供依赖

provide 是在祖先组件中调用的函数,用于提供数据给后代组件。它接受两个参数,第一个参数是一个键(key),用于标识提供的数据,第二个参数是要提供的数据本身。

先写一个祖先组件:

// 祖先组件C1
import { provide } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js'
import C2 from './C2.js'

let template = `
    <C2/>
`

export default {
    components: { C2 },
    setup() {
        provide('mes', '我是祖先组件C1')
    },
    template
}

注意,上面的祖先组件引用了一个C2组件在下面注入依赖部分

应用层 Provide

除了在一个组件中提供依赖,我们还可以在整个应用层面提供依赖:

import { createApp } from 'vue'

const app = createApp({})

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

在应用级别提供的数据在该应用内的所有组件中都可以注入。这在你编写插件时会特别有用,因为插件一般都不会使用组件形式来提供值。

inject注入依赖

C2组件如下,要想获取祖先组件提供的依赖,可以使用inject(),inject 是在后代组件中调用的函数,用于从祖先组件中注入提供的数据。它接受一个参数,即要注入的数据的键。

// 后代组件C2
import { inject } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js'

let template = `
    <div>{{mes}}</div>
`

export default {
    setup() {
        let mes = inject('mes')

        return { mes }
    },
    template
}

另外,inject可以提供一个默认值,如果在祖先组件中没有提供该数据,可以通过第二个参数设置一个默认值。

let mes = inject('mes', '祖先组件没有提供mes值')

使用 inject 时,数据流是单向的,即祖先组件提供数据,后代组件注入数据,而不是相反。也不能在兄弟组件间使用这种依赖注入,就好比你只能从祖先那里继承遗产,但不能在兄弟姐妹那里继承遗产。

提供和注入响应式依赖

vue官网提到“当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。当可能需要在注入方组件中更改数据。在这种情况下,推荐在供给方组件内声明并提供一个更改数据的方法函数”

祖先组件

import { ref, provide } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js'
import C2 from './C2.js'

let template = `
    <C2/>
`

export default {
    components: { C2 },
    setup() {
        let mes = ref('收到请回复')
        let updateMes = (message) => mes.value = message

        provide('mes', {
            mes,
            updateMes
        })
    },
    template
}

后代组件

import { inject } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js'

let template = `
    <div>{{mes}}</div>
    <button v-on:click='updateMes("复")'>回复</button>
`

export default {
    setup() {
        let { mes, updateMes } = inject('mes')

        return { mes, updateMes }
    },
    template
}

结语

这种依赖注入的机制使得组件之间的通信更加灵活,尤其在跨层级的组件通信时,provideinject 提供了一种方便的方式。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值