Vue依赖注入,详细解析

news2024/11/16 20:42:36

Prop 逐级透传问题​

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

Prop 逐级透传的过程图示

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

provide 和 inject 可以帮助我们解决这一问题 [1]。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

Provide/inject 模式

Provide (提供)​

要为组件后代提供数据,需要使用到 provide 选项:

export default {
  provide: {
    message: 'hello!'
  }
}

对于 provide 对象上的每一个属性,后代组件会用其 key 为注入名查找期望注入的值,属性的值就是要提供的数据。

如果我们需要提供依赖当前组件实例的状态 (比如那些由 data() 定义的数据属性),那么可以以函数形式使用 provide

export default {
  data() {
    return {
      message: 'hello!'
    }
  },
  provide() {
    // 使用函数的形式,可以访问到 `this`
    return {
      message: this.message
    }
  }
}

然而,请注意这不会使注入保持响应性。我们会在后续小节中讨论如何让注入转变为响应式。

应用层 Provide​

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

import { createApp } from 'vue'

const app = createApp({})

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

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

Inject (注入)​

要注入上层组件提供的数据,需使用 inject 选项来声明:

export default {
  inject: ['message'],
  created() {
    console.log(this.message) // injected value
  }
}

注入会在组件自身的状态之前被解析,因此你可以在 data() 中访问到注入的属性:

export default {
  inject: ['message'],
  data() {
    return {
      // 基于注入值的初始数据
      fullMessage: this.message
    }
  }
}

注入别名​

当以数组形式使用 inject,注入的属性会以同名的 key 暴露到组件实例上。在上面的例子中,提供的属性名为 "message",注入后以 this.message 的形式暴露。访问的本地属性名和注入名是相同的。

如果我们想要用一个不同的本地属性名注入该属性,我们需要在 inject 选项的属性上使用对象的形式:

export default {
  inject: {
    /* 本地属性名 */ localMessage: {
      from: /* 注入来源名 */ 'message'
    }
  }
}

这里,组件本地化了原注入名 "message" 所提供的属性,并将其暴露为 this.localMessage

注入默认值​

默认情况下,inject 假设传入的注入名会被某个祖先链上的组件提供。如果该注入名的确没有任何组件提供,则会抛出一个运行时警告。

如果在注入一个值时不要求必须有提供者,那么我们应该声明一个默认值,和 props 类似:

export default {
  // 当声明注入的默认值时
  // 必须使用对象形式
  inject: {
    message: {
      from: 'message', // 当与原注入名同名时,这个属性是可选的
      default: 'default value'
    },
    user: {
      // 对于非基础类型数据,如果创建开销比较大,或是需要确保每个组件实例
      // 需要独立数据的,请使用工厂函数
      default: () => ({ name: 'John' })
    }
  }
}

和响应式数据配合使用​

为保证注入方和供给方之间的响应性链接,我们需要使用 computed() 函数提供一个计算属性:

import { computed } from 'vue'

export default {
  data() {
    return {
      message: 'hello!'
    }
  },
  provide() {
    return {
      // 显式提供一个计算属性
      message: computed(() => this.message)
    }
  }
}

computed() 函数常用于组合式 API 风格的组件中,但它同样还可以用于补充选项式 API 风格的某些用例

使用 Symbol 作注入名​

至此,我们已经了解了如何使用字符串作为注入名。但如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,建议最好使用 Symbol 来作为注入名以避免潜在的冲突。

我们通常推荐在一个单独的文件中导出这些注入名 Symbol:

// keys.js
export const myInjectionKey = Symbol()
// 在供给方组件中
import { myInjectionKey } from './keys.js'

export default {
  provide() {
    return {
      [myInjectionKey]: {
        /* 要提供的数据 */
      }
    }
  }
}
// 注入方组件
import { myInjectionKey } from './keys.js'

export default {
  inject: {
    injected: { from: myInjectionKey }
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1568090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaWeb】Day32.MySQL概述

什么是数据库 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 像我们日常访问的电商网站京东&#xff0c;企业内部的管理系统OA、ERP、CRM这类的系统&#xff0c;以及大家每天都会刷的头条、抖音类的app&#xff0c;那这些大家所…

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

【洛谷 P8695】[蓝桥杯 2019 国 AC] 轨道炮 题解(映射+模拟+暴力枚举+桶排序)

[蓝桥杯 2019 国 AC] 轨道炮 题目描述 小明在玩一款战争游戏。地图上一共有 N N N 个敌方单位&#xff0c;可以看作 2D 平面上的点。其中第 i i i 个单位在 0 0 0 时刻的位置是 ( X i , Y i ) (X_i, Y_i) (Xi​,Yi​)&#xff0c;方向是 D i D_i Di​ (上下左右之一, 用…

零基础如何自学人工智能?推荐优秀的学习路径及方法

人工智能&#xff08;AI&#xff09;是一个广泛且复杂的领域&#xff0c;自学AI可能是一项艰巨的任务&#xff0c;但只要有兴趣和决心&#xff0c;这绝对是可能的。以下是一个零基础自学人工智能的学习路径&#xff0c;旨在帮助那些只有兴趣&#xff0c;但缺乏背景知识的人。 *…

[图解]DDD领域驱动设计伪创新-通用语言05

0 00:00:01,060 --> 00:00:04,370 甚至有的人把这个当成恩典 1 00:00:08,730 --> 00:00:11,500 他认为这个对技术人员有好处 2 00:00:13,010 --> 00:00:14,790 他掌握了主动权 3 00:00:15,730 --> 00:00:16,501 这样的话 4 00:00:16,501 --> 00:00:18,430 你…

【Android Studio】上位机-安卓系统手机-蓝牙调试助手

【Android Studio】上位机-安卓系统手机-蓝牙调试助手 文章目录 前言AS官网一、手机配置二、移植工程三、配置总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 AS官网 AS官网 一、手机配置 Android Studio 下真机调试 二、移植工程 Anro…

有时候在mac上使用IDEA无法访问系统里的文件,比如字体等。

有时候在mac上使用IDEA无法访问系统里的文件&#xff0c;比如字体等。 这里可以打开磁盘访问权限。

网络抓包专题

网络抓包原理 一. 什么是抓包&#xff1f; 在应用的开发调试中&#xff0c;查看软件实际运行时HTTP/HTTPS通信的请求数据和返回数据&#xff0c;从而分析问题的过程就叫做抓包。 通常我们说的抓包主要是分为两种&#xff1a; 使用 Wireshark 抓取传输层的 TCP/UDP 通信包。使…

ideaSSM 校园兼职招聘平台bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 校园兼职招聘平台是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…

深度学习理论基础(二)深度神经网络DNN

目录 一、基础知识点Ⅰ 参数部分Ⅱ 模型部分 二、深度神经网络模型搭建1. 准备数据集2. 划分数据集3. 搭建模型4. 训练网络5. 测试网络6. 保存与导入模型 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&…

ndk ffmpeg

报错&#xff1a; 解决办法&#xff1a; 报错 解决办法&#xff1a;

js猜拳游戏

文章目录 1. 演示效果2. 分析思路3. 代码实现3.1. 方式一3.2. 方式二 1. 演示效果 2. 分析思路 获取玩家的出拳(获取按钮的标签体)获取电脑的出拳(随机数)比较二者的出拳&#xff0c;将比较的结果设置到对应的 span 标签中 3. 代码实现 3.1. 方式一 将点击事件进行动态绑定…

Python网络爬虫(四):b站评论

首先来看一下采集的数据格式: 本文不对数据采集的过程做探讨,直接上代码。首先要在程序入口处bvids列表内替换成自己想要采集的视频bvid号,然后将self.cookies替换成自己的(需要字典格式),代码可以同时爬取多个视频的评论,且爬取的评论较为完整,亲测有效: im…

股权激励和期权激励对比辨析

文章目录 概念定义 收益方式 风险评估 应用和分析 股权激励和期权激励&#xff0c;两者的区别是什么&#xff0c;本文就来梳理对比一下。 概念定义 股权激励&#xff0c;是指上市公司以本公司股票为标的&#xff0c;对其董事、高级管理人员及其他员工进行的长期性激励。取得…

二维相位解包理论算法和软件【全文翻译- 简单的路径依赖检验(2.6)】

将公式 2.33 【见前面的文章中】代入公式 2.2,可得 其中积分 代表与路径无关的解,只捕捉 φ 的非旋转成分,以及 代表包含 φ 旋转部分的路径依赖成分。 需要强调的是,F(r)(或 φ(r))中的旋转分量是二维相位解包中路径依赖的唯一来源。相位中的旋转成分是残差的原因。可…

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

【Python系列】 yaml中写入数据

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

680.验证回文串II-力扣

680.验证回文串II-力扣 给你一个字符串 s&#xff0c;最多可以从中删除一个字符。 请你判断 s 是否能成为回文字符串&#xff1a;如果能&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false。 示例1&#xff1a; 输入&#xff1a;s “aba” 输出&#xff1a;true示…

自定义树形筛选选择组件

先上效果图 思路&#xff1a;刚开始最上面我用了el-input&#xff0c;选择框里面内容用了el-inputel-tree使用&#xff0c;但后面发现最上面那个可以输入&#xff0c;那岂不是可以不需要下拉就可以使用&#xff0c;岂不是违背了写这个组件的初衷&#xff0c;所以后面改成div自定…

STM32中启用 UART 的特定中断( __HAL_UART_ENABLE_IT函数)开机立即进入中断问题(HAL库)

学习过程中发现启用 UART 的特定中断功能之后&#xff0c;原本应该是等到空闲中断的标志位变化了再进入中断&#xff0c;结果MCU开机就会进入中断&#xff0c;不符合逻辑&#xff0c;所以尝试解决这个问题。 DMA空闲中断 处理 串口接收不定长数据 的文章见以下 原文链接&#…