【Vue】依赖注入

Vue2 写法

用于祖先组件给后代组件传递数据:
① 在祖先组件中配置 provide,指定需要传递的数据(provide 用法类比 data
② 在后代组件中配置 inject,并接收数据(inject 用法类比 props

  • provide 有两种写法:
    对象式写法:只能传递静态信息,不能获取 this
    函数式写法:可以获取并传递 this 的信息,this 指向当前组件实例
  • provide 会被代理成 _provide,我们可以通过 this._provide.属性名 在父组件中获取 provide 对象的属性
  • 注意:在后代组件中,不建议修改祖先组件传递下来的数据
<template>
    <div>
        <button @click="showPro">点击获取 provide 的属性信息</button>

        <hr />
        <Son />
    </div>
</template>

<script>
import Son from './components/Son.vue';

export default {
    name: 'App',
    components: { Son },
    data() {
        return { msg: 'app 组件的数据' };
    },
    /* 配置 provide */
    // 函数式写法,可以通过 this 访问当前组件
    provide() {
        // 设置需要传递的数据
        return { childMsg: this.msg };
    },
    // 对象式写法,只能传递静态数据
    // provide: { childMsg: "静态数据" },
    methods: {
        showPro() {
            // 我们可以通过 this._provided 获取 provide 的对象数据
            console.log('provide 对象数据', this._provided);
        },
    },
};
</script>
<template>
    <div class="son">
        <p>inject:{{ childMsg }}</p>
    </div>
</template>

<script>
export default {
    name: 'Son',
    inject: ['childMsg'], // 配置 inject、 接收祖先组件传递的数据
};
</script>



Vue3 写法

  • 为后代组件提供数据:provide(key, value)
    • key 可以为 String / Symbol ; value 可以为任意类型,包括响应式的状态
    • 提供的响应式状态使后代组件可以由此和提供者建立响应式的联系
  • 注入上层组件提供的数据:inject(key[, 默认值])
    • 如果提供的值是一个 ref,注入进来的会是该 ref 对象,而不会自动解包为其内部的值。这使得注入方能够通过 ref 对象保持和供给方的响应式链接
    • 在一些场景中,默认值可能需要通过调用一个函数或初始化一个类来获取。为避免在用不到默认值的情况下进行不必要的计算或产生副作用,我们可以使用工厂函数来创建默认值,eg: inject(key, () => new ExpensiveClass())
<template>
    <HelloWorld />
    <button @click="textDemo += '~'">update</button>
</template>

<script lang="ts" setup>
import { ref, provide } from 'vue';
import HelloWorld from '@/components/HelloWorld.vue';

const textDemo = ref('Vue.js');

provide('title', textDemo);
</script>
<template>
    {{ val }}
</template>

<script lang="ts" setup>
import { inject } from 'vue';

const val = inject('title', '默认值');
</script>

和响应式数据配合使用

当 provide / inject 响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护

有的时候,我们可能需要在注入方组件中更改数据。在这种情况下,我们推荐在供给方组件内声明并提供一个更改数据的方法函数:

<template>
    <HelloWorld />
    <button @click="textDemo += '~'">update</button>
</template>

<script lang="ts" setup>
import { ref, provide } from 'vue';
import HelloWorld from '@/components/HelloWorld.vue';

const textDemo = ref('Vue.js');

const updateTitle = (val: string) => {
    textDemo.value += val;
};

provide('title', { textDemo, updateTitle }); // 提供依赖及更新依赖的方法
</script>
<template>
    <button @click="updateTitle('+')">update</button>
    {{ textDemo }}
</template>

<script lang="ts" setup>
import { inject } from 'vue';

const { textDemo, updateTitle } = inject<any>('title'); // 注入依赖及更新依赖的方法
</script>
  • 如果想确保提供的数据不能被注入方的组件更改,可以使用 readonly() 来包装提供的值
    eg: provide('read-only-count', readonly(count))
  • readonly() 接收一个对象 ( 不论是响应式还是普通 ) ,返回一个原值的只读代理

使用 Symbol 作注入名

推荐在一个单独的文件中导出这些 Symbol 注入名

// keys.js
import type { InjectionKey } from 'vue';
export const myInjectionKey = Symbol() as InjectionKey<string>;
// 在供给方组件中
import { provide } from 'vue';
import { myInjectionKey } from './keys.js';

provide(myInjectionKey, {
    /* 要提供的数据 */
});
// 在注入方组件中
import { inject } from 'vue';
import { myInjectionKey } from './keys.js';

const injected = inject(myInjectionKey);

应用层 Provide

在应用级别提供的数据在该应用内的所有组件中都可以注入

import { createApp } from 'vue';

const app = createApp({});

app.provide('message', 'hello!');



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值