Vue Provide / Inject 详细介绍(跨组件通信、响应式变化、版本变化)

vue中的provide/inject你知道吗(vue2、vue3)? “依赖注入”主要是解决父子组件传值“props逐级传递”问题。所以,provide/inject的作用就是组件间的传值。 阅读详情

背景

通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。

对于这种情况,我们可以使用一对 provide 和 inject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。

Provide/inject scheme

使用

假设有一个组件A,A组件引入B组件(A为B的父组件) ,B组件引入C组件(B为C的父组件),即A为C的祖先组件,此时二者可以使用provide / inject进行通信。

举例

A.vue

<template>
  <div>
    <B></B>
  </div>
</template>

<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
};
</script>

B.vue

<template>
  <div>
    <C></C>
  </div>
</template>

<script>
import C from "./C.vue";
export default {
  name: "B",
  components: {
    C
  },
};
</script>

C.vue

<template>
  <div>
  </div>
</template>

<script>
export default {
  name: "C"
};
</script>

A与C使用provide / inject方式进行通信

A使用provide

<template>
  <div>
    <B></B>
  </div>
</template>

<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide:{
    name:"leo"
  }
};
</script>

C使用inject

<template>
  <div>
    <span>{{name}}</span>
  </div>
</template>

<script>
export default {
  name: "C",
  inject:["name"]
};
</script>

此时,C已经拿到A中的对应的name。但是,我们可能希望:当A中的name是本身某个可变化的数据时,如下:

<template>
  <div>
    <B></B>
  </div>
</template>

<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide:{
    name:this.name
  },
  data(){
    return {
      name:"leo"
    }
  },
  methods:{
    changeName(){
      this.name = "lion"
    }
  }
};
</script>

我们希望当name改变时(如触发changeName方法),对应的C中的name也要相应改变,但是使用以上方式时,C中的name并未随着改变,此时需要我们进一步处理,即处理响应性。

处理响应性 

在上面的例子中,如果我们更改了name,这个变化并不会反映在 inject 的 name property 中。这是因为默认情况下,provide/inject 绑定并不是响应式的。在vue3中,我们可以通过传递一个 ref property 或 reactive 对象给 provide 来改变这种行为(下面展开)。在我们的例子(vue2)中,如果我们想对祖先组件中的更改做出响应,我们需要将 provide 传值进行改变。

A使用provide,此时传入的应是一个响应式对象(如以下的obj)

<template>
  <div>
    <B></B>
  </div>
</template>

<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide(){
    return {
      obj:this.obj      //传入一个响应式对象
    }
  },
  data(){
    return {
      obj:{
        name:"leo"
      }
    }
  },
  methods:{
    changeName(){
      this.obj.name = "lion"
    }
  }
};
</script>

C使用inject

<template>
  <div>
    <span>{{obj.name}}</span>
  </div>
</template>

<script>
export default {
  name: "C",
  inject:["obj"]    //接收响应式对象
};
</script>

此时A中的name改变,C中的值也会相应跟着变化。

以上为A向C传数据,如果C向A传数据(或者说C需要改变A中的数据),该如何做?

我们这里不让C直接改变A中的数据,而是将A改变数据的方法通过provide传给C,C执行该方法,触发改变A中的数据。

A使用provide传入一个方法

<template>
  <div>
    <span>{{obj.name}}</span>
    <B></B>
  </div>
</template>

<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide(){
    return {
      changeVal:this.changeName      //传入一个方法
    }
  },
  data(){
    return {
      obj:{
        name:"leo"
      }
    }
  },
  methods:{
    changeName(val){          //C中触发该方法执行,此时变成"lion"
      this.obj.name = val
    }
  }
};
</script>

C使用inject

<template>
  <div>
    <span @click="changeName">点击改变A组件数据</span>
  </div>
</template>

<script>
export default {
  name: "C",
  inject:["changeVal"],    //接收一个方法
  methods:{
    changeName(){
      this.changeVal("lion")     //执行此方法,改变A中的数据
    }
  }
};
</script>

以上就是在vue2中对provide / inject的基本使用。

vue3中使用

Provide

在 setup() 中使用 provide 时,我们首先从 vue 显式导入 provide 方法。这使我们能够调用 provide 来定义每个 property。

provide 函数允许你通过两个参数定义 property:

  1. name (<String> 类型)
  2. value

使用A组件,provide 的值可以按如下方式重构:

<template>
  <C />
</template>

<script>
import { provide } from 'vue'
import C from './C.vue'

export default {
  components: {
    C
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>

Inject

在 setup() 中使用 inject 时,也需要从 vue 显式导入。导入以后,我们就可以调用它来定义暴露给我们的组件方式。

inject 函数有两个参数:

  1. 要 inject 的 property 的 name
  2. 默认值 (可选)

使用C组件,可以使用以下代码对其进行重构:

<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>

上面提到,在vue3中处理响应性的方式

为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive

<template>
  <C />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import C from './C.vue'

export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>

现在,如果这两个 property 中有任何更改,C组件也将自动更新!

同样的,需要在C中修改它的祖先组件的数据,需像vue2一样在provide传入一个方法

<template>
  <C />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import C from './C.vue'

export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)     //传入一个方法
  }
}
</script>

C中使用inject

<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation      //执行该方法,触发祖先组件方法执行,从而改变数据
    }
  }
}
</script>

最后,如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly

<template>
  <C />
</template>

<script>
import { provide, reactive, readonly, ref } from 'vue'
import C from './C.vue'

export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }
    // 使用readonly,数据只读
    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>

总结:主要介绍了provide / inject 的基本使用以及在vue2、vue3中使用的区别。 

Vue组件:依赖注入provideinject的使用 通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦。provideinject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。 阅读详情

相关推荐

Vue 3 响应式核心揭秘:掌握 ref、reactive 与 Provide/Inject 的终极指南

Vue 3 的组合式 API(Composition API)为前端开发带来了革命性的变化,其核心是强大的响应式系统。通过 ref 和 reactive,开发者可以轻松管理单值和复杂对象的响应式状态,而 Provide/Inject 提供了一种优雅的方式来实现跨层级组件通信。这些技术极大地简化了状态管理和组件交互,特别适合构建现代化的单页应用(SPA)。然而,响应式系统的灵活性也带来了挑战。例如,ref 和 reactive 的选择、响应式丢失、深层嵌套对象的处理,以及 Provide/Inject

zimin的专栏 1192

vueprovide的用法_Vue中使用provideinject

相信大家在工作中一定遇到过多层嵌套组件,而vue 的组件数据通信方式又有很多种。比如vuex、&dollar;parent与&dollar;children、prop、&dollar;emit与&dollar;on、&dollar;attrs与&dollar;lisenters、eventBus、ref。今天主要为大家分享的是provide和inje...

weixin_39811478的博客 2万+

vue中可响应式provide/inject的实现

一、基本概念 当需要访问父级组件的实例的时候,我们可以通过$parent属性来获取父级组件的实例。但是,在嵌套了多层组件并且想在较深层级的子组件中获取顶级父级组件时通过这个属性就不太好了。这个时候就要用到vue中依赖注入的概念了。 vue中依赖注入的具体实现是通过两个实例选项——provide/inject实现的。 provide选项允许我们指定我们想要提供给后代组件的数据/方法。示例: export default { provide: function(){ retur

仰望星空的代码 1881

vueprovide的使用

provide的使用方法: 在父组件中定义provide provide和data,methods同级 provide中返回值是一个对象,相当于将对象中的内容注入到子孙组件 子孙组件使用inject: [ 由provide键名组成的数组 ] ,来获取父级组件的方法或者其他属性 具体看代码 父组件: provide(){ return{ closeCurrent:this.closeCurrent, reload: this.routeReload // 刷

xuebinsunwumei的博客 1万+

Vue中的Provide/Inject 实现响应式数据

Vue中, Provide/Inject实现了跨组件通信。但可惜数据并不是响应式的(设计如此)。 提示:provideinject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的 以上引用自官网 可能之所以这样设计,是为了避免数据的混乱。就如同props不能被子组件直接修改一样。 从代码角度讲 data() { return { foo: 'foo', bar: 'bar...

qq_57558631的博客 5023

总结vue2和vue3区别

vue2和vue3的区别,以及vue3中实用属性

weixin_67490903的博客 4786

Provide/Inject

当我们以如上的形式书写代码的时候,其实相当于对this.foo和this.baz做了一层浅拷贝,固当子组件inject的时候已经丢失了响应式功能了。但由于仅仅是浅拷贝,所以响应式对象的属性仍旧是响应式的。然而,如果你传入了一个可监听的对象,那么其对象的property还是可响应的。而且这样做有一个好处,即无法直接修改computedProperty的值,因为他是一个计算属性。此时整条数据的响应式的状态并不会丢失。可能之所以这样设计,是为了避免数据的混乱。依照这个思路,如果我们希望整个数据都是响应式的。...

MR.杜的博客 150

从原理到实战:vue中的provide/inject让你的代码更优美

从原理到实战:vue中的provide/inject让你的代码更优美

希望看完文章的你能够带着答案离开。 1万+

Vue3全局组件通信provide / inject

顾名思义,爷孙组件是比 父子组件通信 要更深层次的引用关系(也有称之为 “隔代组件”):C组件引入到B组件里,B组件引入到A组件里渲染,此时A是C的爷爷级别(可能还有更多层级关系),如果你用 props ,只能一级一级传递下去,那就太繁琐了,因此我们需要更直接的通信方式。😜😜😜因为上下级的关系的一致性,爷孙组件通信的方案也适用于 父子组件通信 ,只需要把爷孙关系换成父子关系即可。

老电影故事的博客 7984

Vue3 中的 provideinject 详解:实现跨组件通信

Vue3中的provide/inject和defineOptions详解 provide/injectVue3实现跨层级组件通信的API,解决了props逐层传递的问题。祖先组件provide提供数据,后代组件inject注入数据,支持响应式处理和修改方法封装。最佳实践包括使用Symbol避免命名冲突、应用层provide全局数据,适合主题切换、国际化等场景。 defineOptions是Vue3.3+的宏命令,允许在<script setup>中定义组件选项(如name、inheritAtt

2401_83607690的博客 3020

ProvideInject 的用法

前言 父子组件传参可以通过props和emit来实现,但是当组件的层次结构比较深时,props和emit就没什么作用了。vue为了解决这个提出了Provide / Inject,知道这个东西,但是一直没用过,最近碰到了一个问题,踩了一些坑,在这里记录一下 备注: 我安装的是vue3.x,v-model用的是3.x的语法。 2.x和3.x用法一致,我这里是用2.x写的 通用知识 基本用法 provide 选项应该是:一个对象或返回一个对象的函数 inject 选项应该是:一个字符串数组,或 一个对象,对象的

weixin_41897680的博客 2万+

Vue 爷孙组件通讯之:Provide / Inject 详细介绍

假设有一个组件A,A组件引入B组件(A为B的父组件) ,B组件引入C组件(B为C的父组件),即A为C的祖先组件,此时二者可以使用provide / inject进行通信。时,通常使用的是 props 和 emit,父传子时,使用的是 props,如果是父组件传孙组件时,层层传递非常麻烦。我们这里不让C直接改变A中的数据,而是将A改变数据的方法通过provide传给C,C执行该方法,触发改变A中的数据。以上为A向C传数据,如果C向A传数据(或者说C需要改变A中的数据),该如何做?

A_one2010的博客 1828

详细讲解vue2组件通信()——多代传递provide/inject

学一个知识点,我们得知道这个知识点是用来干嘛的?为什么选择用它?怎么用? provide/inject的作用 vue官网原话【允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深, 并在其上下游关系成立的时间里始终生效。】也就是如果当前组件设置了provide传递数据, 那么在当前组件的所有后辈组件中,都可以使用inject接收这个数据。 provide/inject被选择的理由 组件通信的方式那么多,多代传递数据的通信方式还有vuex,$root,全局事件总线。为什 么选择provide/

浪头的博客 6284

vueprovide/inject实现响应式数据监听

provide/inject 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。 无论多少层都会被子组建拿到 主要用在高阶组件 provide 选项应该是一个对象或返回一个对象的函数。 inject 选项应该是:一个字符串数组,或 一个对象,对象的 key 是本地的绑定名 提示: provideinject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。 正常使用

yw00yw的博客 1万+

Vue3 关于 provideinject 的用法

前端项目中牵扯的最多的莫过于组件之间的传值了,除了最最常用的。

fang_my的博客 5914

Vue3 Provide / Inject

provideinjectVue 3中用于实现依赖注入的API。它们允许一个组件(通常是祖先组件)向其后代组件提供数据或方法,而无需通过中间组件逐层传递。这种方式类似于依赖注入框架中的提供者和注入器,极大地简化了组件间的通信Provide:在一个组件中声明要提供给后代组件的数据或方法。Inject:在后代组件中声明要注入的依赖,从祖先组件中获取提供的数据或方法。provideinjectVue 3中强大的依赖注入工具,简化了组件间的通信,特别是在处理深层组件结构和共享全局依赖时。

Flying_Fish_roe的博客 4395

Vue中的provideinject

特性用法组件选项provide(对象/函数)、inject(数组/对象)导入provideinject函数,在 setup 中调用响应式需手动传递响应式对象(如 data 中的属性)原生支持refreactive响应式传递类型支持较弱(需手动注释)可通过实现强类型约束灵活性依赖组件选项,灵活性较低可在 setup 中动态提供/注入,灵活性更高核心作用一致:跨层级通信,减少 props 传递成本,适用于共享低频变化的全局配置或插件内部通信

fmk1023的博客 1367

第九节: Vue 3 中的 provideinject:优雅的跨组件通信

本文主要介绍vue3 中provide , inject的使用, 实现跨Vue3组件通信

我们专注于分享最实用的编程技术和干货,帮助你提升编程能力,感谢您的支持和关注! 1760
上一篇: 分享 5 个你现在就能用上的 Js ES12 新特性(数字分隔符、replaceAll()、Promise.any()、......)
下一篇: Vue 常见面试题汇总(这些技巧你真的都掌握了吗?呕心沥血2w字整理)
前端不释卷leo
前端不释卷leo 新星创作者: 前端开发技术领域 新星创作者: 前端开发技术领域
博客等级 码龄8年 3万+粉丝 85原创
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

前端不释卷leo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值