我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vue3全局组件通信之provide/inject怎么使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vue3全局组件通信之provide/inject怎么使用

本篇内容介绍了“Vue3全局组件通信之provide/inject怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1、前言

顾名思义,爷孙组件是比 父子组件通信 要更深层次的引用关系(也有称之为 “隔代组件”):

C组件引入到B组件里,B组件引入到A组件里渲染,此时A是C的爷爷级别(可能还有更多层级关系),如果你用 props ,只能一级一级传递下去,那就太繁琐了,因此我们需要更直接的通信方式。

他们之间的关系如下,Grandson.vue 并非直接挂载在 Grandfather.vue 下面,他们之间还隔着至少一个 Son.vue (可能有多个):

Grandfather.vue└─Son.vue  └─Grandson.vue

因为上下级的关系的一致性,爷孙组件通信的方案也适用于 父子组件通信 ,只需要把爷孙关系换成父子关系即可。

2、provide / inject

这个特性有两个部分:Grandfather.vue 有一个 provide 选项来提供数据,Grandson.vue 有一个 inject 选项来开始使用这些数据。

  • Grandfather.vue 通过 provide 向 Grandson.vue 传值(可包含定义好的函数)

  • Grandson.vue 通过 inject 向 Grandfather.vue 触发爷爷组件的事件执行

无论组件层次结构有多深,发起 provide 的组件都可以作为其所有下级组件的依赖提供者
这一部分的内容变化都特别大,但使用起来其实也很简单,不用慌,也有相同的地方:

  • 父组件不需要知道哪些子组件使用它 provide 的 property

  • 子组件不需要知道 inject property 来自哪里

另外,要切记一点就是:provide 和 inject 绑定并不是可响应的。这是刻意为之的,但如果传入了一个可监听的对象,那么其对象的 property 还是可响应的。

3、发起 provide

我们先来回顾一下 2.x 的用法:

export default {  // 定义好数据  data () {    return {      tags: [ '中餐', '粤菜', '烧腊' ]    }  },  // provide出去  provide () {    return {      tags: this.tags    }  }}

旧版的 provide 用法和 data 类似,都是配置为一个返回对象的函数。
3.x 的新版 provide, 和 2.x 的用法区别比较大。

在 3.x , provide 需要导入并在 setup 里启用,并且现在是一个全新的方法。
每次要 provide 一个数据的时候,就要单独调用一次。
每次调用的时候,都需要传入 2 个参数:

参数类型说明
keystring数据的名称
valueany数据的值

来看一下如何创建一个 provide:

// 记得导入provideimport { defineComponent, provide } from 'vue'export default defineComponent({  // ...  setup () {    // 定义好数据    const msg: string = 'Hello World!';    // provide出去    provide('msg', msg);  }})

操作非常简单对吧,但需要注意的是,provide 不是响应式的,如果你要使其具备响应性,你需要传入响应式数据

4、接收 inject

也是先来回顾一下 2.x 的用法:

export default {  inject: ['tags'],  mounted () {    console.log(this.tags);  }}

旧版的 inject 用法和 props 类似,3.x 的新版 inject, 和 2.x 的用法区别也是比较大。

在 3.x, inject 和 provide 一样,也是需要先导入然后在 setup 里启用,也是一个全新的方法。
每次要 inject 一个数据的时候,就要单独调用一次。
每次调用的时候,只需要传入 1 个参数:

参数类型说明
keystring与provide对应的数据名称
// 记得导入injectimport { defineComponent, inject } from 'vue'export default defineComponent({  // ...  setup () {    const msg: string = inject('msg') || '';  }})

也是很简单(写 TS 的话,由于 inject 到的值可能是 undefined,所以要么加个 undefined 类型,要么给变量设置一个空的默认值)。

5、响应性数据的传递与接收

之所以要单独拿出来说, 是因为变化真的很大

在前面我们已经知道,provide 和 inject 本身不可响应,但是并非完全不能够拿到响应的结果,只需要我们传入的数据具备响应性,它依然能够提供响应支持。

我们以 ref 和 reactive 为例,来看看应该怎么发起 provide 和接收 inject。

先在 Grandfather.vue 里 provide 数据:

export default defineComponent({  // ...  setup () {    // provide一个ref    const msg = ref<string>('Hello World!');    provide('msg', msg);    // provide一个reactive    const userInfo: Member = reactive({      id: 1,      name: 'Petter'    });    provide('userInfo', userInfo);    // 2s 后更新数据    setTimeout(() => {      // 修改消息内容      msg.value = 'Hi World!';      // 修改用户名      userInfo.name = 'Tom';    }, 2000);  }})

在 Grandsun.vue 里 inject 拿到数据:

export default defineComponent({  setup () {    // 获取数据    const msg = inject('msg');    const userInfo = inject('userInfo');    // 打印刚刚拿到的数据    console.log(msg);    console.log(userInfo);    // 因为 2s 后数据会变,我们 3s 后再看下,可以争取拿到新的数据    setTimeout(() => {      console.log(msg);      console.log(userInfo);    }, 3000);    // 响应式数据还可以直接给 template 使用,会实时更新    return {      msg,      userInfo    }  }})

非常简单,非常方便!!!

响应式的数据 provide 出去,在子孙组件拿到的也是响应式的,并且可以如同自身定义的响应式变量一样,直接 return 给 template 使用,一旦数据有变化,视图也会立即更新。

但上面这句话有效的前提是,不破坏数据的响应性,比如 ref 变量,你需要完整的传入,而不能只传入它的 value,对于 reactive 也是同理,不能直接解构去破坏原本的响应性

切记!切记!!!

6、引用类型的传递与接收 (针对非响应性数据的处理)

provide 和 inject 并不是可响应的,这是官方的故意设计,但是由于引用类型的特殊性,在子孙组件拿到了数据之后,他们的属性还是可以正常的响应变化。

先在 Grandfather.vue 里 provide 数据:

export default defineComponent({  // ...  setup () {    // provide 一个数组    const tags: string[] = [ '中餐', '粤菜', '烧腊' ];    provide('tags', tags);    // provide 一个对象    const userInfo: Member = {      id: 1,      name: 'Petter'    };    provide('userInfo', userInfo);    // 2s 后更新数据    setTimeout(() => {      // 增加tags的长度      tags.push('叉烧');      // 修改userInfo的属性值      userInfo.name = 'Tom';    }, 2000);  }})

在 Grandsun.vue 里 inject 拿到数据:

export default defineComponent({  setup () {    // 获取数据    const tags: string[] = inject('tags') || [];    const userInfo: Member = inject('userInfo') || {      id: 0,      name: ''    };    // 打印刚刚拿到的数据    console.log(tags);    console.log(tags.length);    console.log(userInfo);    // 因为 2s 后数据会变,我们 3s 后再看下,能够看到已经是更新后的数据了    setTimeout(() => {      console.log(tags);      console.log(tags.length);      console.log(userInfo);    }, 3000);  }})export default defineComponent({  setup () {    // 获取数据    const tags: string[] = inject('tags') || [];    const userInfo: Member = inject('userInfo') || {      id: 0,      name: ''    };    // 打印刚刚拿到的数据    console.log(tags);    console.log(tags.length);    console.log(userInfo);    // 因为 2s 后数据会变,我们 3s 后再看下,能够看到已经是更新后的数据了    setTimeout(() => {      console.log(tags);      console.log(tags.length);      console.log(userInfo);    }, 3000);  }})

引用类型的数据,拿到后可以直接用,属性的值更新后,子孙组件也会被更新。
但是!!!由于不具备真正的响应性,return 给模板使用依然不会更新视图,如果涉及到视图的数据,请依然使用 响应式 API 。

7、基本类型的传递与接收 (针对非响应性数据的处理)

基本数据类型被直接 provide 出去后,再怎么修改,都无法更新下去,子孙组件拿到的永远是第一次的那个值。

先在 Grandfather.vue 里 provide 数据:

export default defineComponent({  // ...  setup () {    // provide 一个数组的长度    const tags: string[] = [ '中餐', '粤菜', '烧腊' ];    provide('tagsCount', tags.length);    // provide 一个字符串    let name: string = 'Petter';    provide('name', name);    // 2s 后更新数据    setTimeout(() => {      // tagsCount 在 Grandson 那边依然是 3      tags.push('叉烧');      // name 在 Grandson 那边依然是 Petter      name = 'Tom';    }, 2000);  }})

在 Grandsun.vue 里 inject 拿到数据:

export default defineComponent({  setup () {    // 获取数据    const name: string = inject('name') || '';    const tagsCount: number = inject('tagsCount') || 0;    // 打印刚刚拿到的数据    console.log(name);    console.log(tagsCount);    // 因为 2s 后数据会变,我们 3s 后再看下    setTimeout(() => {      // 依然是 Petter      console.log(name);      // 依然是 3      console.log(tagsCount);    }, 3000);  }})

很失望,并没有变化。


那么是否一定要定义成响应式数据或者引用类型数据呢?

当然不是,我们在 provide 的时候,也可以稍作修改,让它能够同步更新下去。

先在 Grandfather.vue 里 provide 数据:

export default defineComponent({  // ...  setup () {    // provide 一个数组的长度    const tags: string[] = [ '中餐', '粤菜', '烧腊' ];    provide('tagsCount', (): number => {      return tags.length;    });    // provide 字符串    let name: string = 'Petter';    provide('name', (): string => {      return name;    });    // 2s 后更新数据    setTimeout(() => {      // tagsCount 现在可以正常拿到 4 了      tags.push('叉烧');      // name 现在可以正常拿到 Tom 了      name = 'Tom';    }, 2000);  }})

再来 Grandsun.vue 里修改一下 inject 的方式,看看这次拿到的数据:

export default defineComponent({  setup () {    // 获取数据    const tagsCount: any = inject('tagsCount');    const name: any = inject('name');    // 打印刚刚拿到的数据    console.log(tagsCount());    console.log(name());    // 因为 2s 后数据会变,我们 3s 后再看下    setTimeout(() => {      // 现在可以正确得到 4      console.log(tagsCount());      // 现在可以正确得到 Tom      console.log(name());    }, 3000);  }})

这次可以正确拿到数据了,看出这2次的写法有什么区别了吗?

基本数据类型,需要 provide 一个函数,将其 return 出去给子孙组件用,这样子孙组件每次拿到的数据才会是新的。
但由于不具备响应性,所以子孙组件每次都需要重新通过执行 inject 得到的函数才能拿到最新的数据。

由于不具备真正的响应性,return 给模板使用依然不会更新视图,如果涉及到视图的数据,请依然使用 响应式 API 。

“Vue3全局组件通信之provide/inject怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vue3全局组件通信之provide/inject怎么使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue3全局组件通信之provide/inject怎么使用

本篇内容介绍了“Vue3全局组件通信之provide/inject怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、前言顾名思义,爷
2023-07-06

Vue3全局组件通信之provide / inject详解

这篇文章主要介绍了Vue3全局组件通信之provide / inject,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-14

Vue3全局组件通信之provide/inject源码分析

1、前言顾名思义,爷孙组件是比父子组件通信要更深层次的引用关系(也有称之为“隔代组件”):C组件引入到B组件里,B组件引入到A组件里渲染,此时A是C的爷爷级别(可能还有更多层级关系),如果你用props,只能一级一级传递下去,那就太繁琐了,因此我们需要更直接的通信方式。他们之间的关系如下,Grandson.vue并非直接挂载在Grandfather.vue下面,他们之间还隔着至少一个Son.vue(可能有多个):Grandfather.vue└─Son.vue└─Grandson.vue因为上下
2023-05-14

Vue3插件中怎么使用Provide和Inject

今天小编给大家分享一下Vue3插件中怎么使用Provide和Inject的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。为什么
2023-07-04

Vue3之Teleport组件怎么使用

Teleport组件解决的问题版本:3.2.31如果要实现一个“蒙层”的功能,并且该“蒙层”可以遮挡页面上的所有元素,通常情况下我们会选择直接在标签下渲染“蒙层”内容。如果在Vue.js2中实现这个功能,只能通过原生DOMAPI来手动搬运DOM元素实现,这就会使得元素的渲染与Vue.js的渲染机制脱节,并会导致各种可预见或不可遇见的问题。Vue.js3中内建的Teleport组件,可以将指定内容渲染到特定容器中,而不受DOM层级的限制。可以很好的解决这个问题。下面,我们来看看Teleport组件
2023-05-14

Vue2中如何使用全局事件总线实现任意组件间通信

全局事件总线就是一种组件间通信的方式,适用于任意组件间通信,下面这篇文章主要给大家介绍了关于Vue2中如何使用全局事件总线实现任意组件间通信的相关资料,需要的朋友可以参考下
2022-12-28

vue怎么使用Vue.extend创建全局toast组件

本篇内容主要讲解“vue怎么使用Vue.extend创建全局toast组件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue怎么使用Vue.extend创建全局toast组件”吧!Vue.ex
2023-07-05

Vue3兄弟组件传值之mitt怎么安装使用

本篇内容介绍了“Vue3兄弟组件传值之mitt怎么安装使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!比起 Vue 实例上的 EventB
2023-07-02

Vue组件的自定义事件和全局事件总线怎么使用

这篇“Vue组件的自定义事件和全局事件总线怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue组件的自定义事件和全局
2023-07-05

vue中怎么使用svg封装全局消息提示组件

本文小编为大家详细介绍“vue中怎么使用svg封装全局消息提示组件”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue中怎么使用svg封装全局消息提示组件”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。先看效果图
2023-06-30

vue前端重构computed及watch组件通信怎么使用

这篇文章主要介绍“vue前端重构computed及watch组件通信怎么使用”,在日常操作中,相信很多人在vue前端重构computed及watch组件通信怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-06-30

怎么封装一个vue中也可使用的uniapp全局弹窗组件

这篇文章主要介绍了怎么封装一个vue中也可使用的uniapp全局弹窗组件的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么封装一个vue中也可使用的uniapp全局弹窗组件文章都会有所收获,下面我们一起来看看吧
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录