在父子组件传递数据时,通常使用的是 props 和 emit,父传子时,使用的是 props,如果是父组件传孙组件时,就需要先传给子组件,子组件再传给孙组件,如果多个子组件或多个孙组件使用时,就需要传很多次,会很麻烦。

像这种情况,可以使用 provide 和 inject 解决这种问题,不论组件嵌套多深,父组件都可以为所有子组件或孙组件提供数据,父组件使用 provide 提供数据,子组件或孙组件 inject 注入数据。同时兄弟组件之间传值更方便。

一、Vue2 的 provide / inject 使用

provide :是一个对象,里面是属性和值。如:

provide:{
info:"值"
}

如果 provide 需要使用 data 内的数据时,这样写就会报错。访问组件实例 property 时,需要将 provide 转换为返回对象的函数。

provide(){
return{
info: this.msg
}
}

inject :是一个字符串数组。如:

inject: [ 'info' ]

接收上边 provide 提供的 info 数据,也可以是一个对象,该对象包含 from 和 default 属性,from 是可用做的注入内容中搜索用的 key,default 属性是指定默认值。

在 vue2 中 project / inject 应用:

//父组件
export default{
provide:{
info:"提供数据"
}
}
//子组件
export default{
inject:['info'],
mounted(){
console.log("接收数据:", this.info) // 接收数据:提供数据
}
}

provide / inject 类似于消息的订阅和发布。provide 提供或发送数据, inject 接收数据。

二、Vue3 的 provide / inject 使用

在组合式 API 中使用 provide/inject,两个只能在 setup 期间调用,使用之前,必须从 vue 显示导入 provide/inject 方法。

provide 函数接收两个参数:

provide( name,value )

name:定义提供 property 的 name 。

value :property 的值。

使用时:

import { provide } from "vue"
export default {
setup(){
provide('info',"值")
}
}

inject 函数有两个参数:

inject(name,default)

name:接收 provide 提供的属性名。

default:设置默认值,可以不写,是可选参数。

使用时:

import { inject } from "vue"
export default {
setup(){
inject('info',"设置默认值")
}
}

完整实例1:provide/inject实例

//父组件代码
<script>
import { provide } from "vue"
export default {
setup(){
provide('info',"值")
}
}
</script> //子组件 代码
<template>
{{info}}
</template>
<script>
import { inject } from "vue"
export default {
setup(){
const info = inject('info')
return{
info
}
}
}
</script>

三、添加响应性

为了给 provide/inject 添加响应性,使用 ref 或 reactive 。

完整实例2:provide/inject 响应式

//父组件代码
<template>
<div>
info:{{info}}
<InjectCom ></InjectCom>
</div>
</template>
<script>
import InjectCom from "./InjectCom"
import { provide,readonly,ref } from "vue"
export default {
setup(){
let info = ref("今天你学习了吗?")
setTimeout(()=>{
info.value = "不找借口,立马学习"
},2000)
provide('info',info)
return{
info
}
},
components:{
InjectCom
}
}
</script> // InjectCom 子组件代码
<template>
{{info}}
</template>
<script>
import { inject } from "vue"
export default {
setup(){
const info = inject('info')
setTimeout(()=>{
info.value = "更新"
},2000)
return{
info
}
}
}
</script>

上述示例,在父组件或子组件都会修改 info 的值。

provide / inject 类似于消息的订阅和发布,遵循 vue 当中的单项数据流,什么意思呢?就是数据在哪,修改只能在哪,不能在数据传递处修改数据,容易造成状态不可预测。

在订阅组件内修改值的时候,可以被正常修改,如果其他组件也使用该值的时候,状态容易造成混乱,所以需要在源头上规避问题。

readonly 只读函数,使用之前需要引入,如果给变量加上 readonly 属性,则该数据只能读取,无法改变,被修改时会发出警告,但不会改变值。

使用方法:

import { readonly } from "vue"
let info = readonly('只读info值')
setTimout(()=>{
info="更新info" //两秒后更新info的值
},2000)

运行两秒后,浏览器发出警告,提示 info 值不可修改。

所以我们就给provide发射出去的数据,添加一个只读属性,避免发射出去的数据被修改。

完整实例2的 provide 处添加 readonly 。

provide('info', readonly(info))

在子组件修改值的时候,会有一个只读提醒。

修改值的时候,还是需要在 provide 发布数据的组件内修改数据,所以会在组件内添加修改方法,同时也发布出去,在子组件处调用就可以了。如:

//发布
let info = ref("今天你学习了吗?")
const changeInfo = (val)=>{
info.value = val
}
provide('info',readonly(info))
provide('changeInfo',changeInfo) //订阅
const chang = inject('changeInfo')
chang('冲向前端工程师')

完整示例3:修改数据

// 父组件代码
<template>
<div>
info:{{info}}
<InjectCom ></InjectCom>
</div>
</template> <script>
import InjectCom from "./InjectCom"
import { provide,readonly,ref } from "vue"
export default {
setup(){
let info = ref("今天你学习了吗?")
const changeInfo = (val)=>{
info.value = val
}
provide('info',readonly(info))
provide('changeInfo',changeInfo)
return{
info
}
},
components:{
InjectCom
}
}
</script> //InjectCom 子组件代码
<template>
<div>
<button @click="chang('冲向前端工程师')">更新值</button>
</div>
</template>
<script>
import { inject } from "vue"
export default {
setup(){
const info = inject('info')
const chang = inject('changeInfo')
return{
info,
chang
}
}
}
</script>

vue 3 学习笔记 (八)——provide 和 inject 用法及原理的更多相关文章

  1. Vue.js学习笔记(2)vue-router

    vue中vue-router的使用:

  2. Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  3. vue.js 学习笔记3——TypeScript

    目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...

  4. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...

  5. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  6. Vue.js学习笔记:在元素 和 template 中使用 v-if 指令

    f 指令 语法比较简单,直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " ...

  7. 【opencv学习笔记八】创建TrackBar轨迹条

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...

  8. go微服务框架kratos学习笔记八 (kratos的依赖注入)

    目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...

  9. Redis学习笔记八:集群模式

    作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...

随机推荐

  1. 【UE4 C++】UGameplayStatics 源代码

    // Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" # ...

  2. 短短 29 天,应对高峰 100W+ 访问,看浙大如何交出满分答卷

    疫情期间"停课不停教,停课不停学",线上开课第一天,浙江大学网上开课平台访问量即突破100 万次,访客数3万余人,最高峰达 1.1万人同时在线,发起课程直播2000余场,然而系统却 ...

  3. 锚点布局anchorlayout在kv中的引用

    from kivy.app import App from kivy.uix.anchorlayout import AnchorLayout from kivy.uix.button import ...

  4. Django+Vue跨域配置与经验

    一.原理 同源?同源策略? 同源的定义是:两个页面的协议.端口和域名都相同 同源的例子: 不同源的例子: 同源策略SOP(Same origin policy)是一种浏览器约定,它是浏览器最核心也最基 ...

  5. OO第三单元——JML规格化设计

    OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...

  6. 攻防世界 杂项 2.embarrass

    解1: linux环境下直接strings misc_02.pcapng | grep flag可得flag. 解2: 使用wireshark搜索flag. 解3: winhex搜索flag.

  7. shell调用另一个脚本的三种方式fork/exec/source

    exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息. bash shell的命令分为两 ...

  8. Linux 显示ip、dns、网关等命令

    在新版的ubuntu 终端里输入命令nm-tool, 想查看网络参数设置, 没想到却返回如下内容:   未找到 'nm-tool' 命令,您要输入的是否是:  命令 'dm-tool' 来自于包 'l ...

  9. S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...

  10. Docker 部署前后端项目

    Docker 部署前后端项目 平生不会相思,才会相思,便害相思. 简介:都是被逼的,从零开始一个Docker 部署九个微服务和三个前端项目.其中,这些服务需要用到Nacos.MySQL.Nginx.E ...