provide/inject 依赖注入

254 阅读1分钟

在 Vue 中,provideinject 主要用于父子组件之间的数据传递。provide 让父组件提供数据,inject 让子组件从父组件注入数据。

provide(key,value) 接收两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。

inject(key,defaultValue) 接收两个参数:第一个参数是注入的 key,第二个参数是可选的,即在没有匹配到 key 时使用的默认值。

下面演示如何使用:

父组件

<template>
  <div class="provide-container" :style="{ height: height + 'px' }">
    <h1>父组件</h1>
    <n-button @click="handleClick">点击</n-button>
    <h2>{{ data }}</h2>
    <div>
      <A></A>
      <B></B>
    </div>
  </div>
</template>
<script lang="ts" setup>
import A from '@/components/provide/A.vue'
import B from '@/components/provide/B.vue'
import { provide, ref } from 'vue'

let height = ref()
height.value = window.innerHeight
let count = ref(0)
let data = ref(0)
const handleClick = () => {
  count.value++
}
const handleChange = (val) => {
  data.value += val
}
provide('ParentComponent', {
  msg: '父组件',
  count,
  handleChange,
})
</script>
<style lang="scss" scoped>
.provide-container {
  height: 100%;
  background: #e6e6e6;
  text-align: center;
}
</style>

A组件

<template>
  <div class="A-container">
    <h2 class="name">A组件</h2>
    <h3>父组件传递的数据:{{ ParentComponent.count }}</h3>
    <div>
      <DeepA></DeepA>
    </div>
  </div>
</template>
<script lang="ts" setup>
import DeepA from '@/components/provide/deepA.vue'
import { provide, inject, ref } from 'vue'
const ParentComponent = inject('ParentComponent')
</script>
<style scoped lang="scss">
.A-container {
  background: #54a29e;
  height: 400px;
  width: 400px;
}
</style>

B组件

<template>
  <div class="B-container">
    <h2 class="name">B组件</h2>
    <div>
      <h3>父组件传递的数据:{{ ParentComponent.count }}</h3>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { provide, inject, ref } from 'vue'
const ParentComponent = inject('ParentComponent')
</script>
<style scoped lang="scss">
.B-container {
  background: palegreen;
  height: 400px;
  width: 400px;
}
</style>

子孙组件

<template>
  <div class="deepA-container">
    <h3 class="name">deepA组件</h3>
    <h4>父组件传递的数据:{{ ParentComponent.count }}</h4>
    <n-button @click="handleClick()">点击父组件方法</n-button>
  </div>
</template>
<script lang="ts" setup>
import { inject } from 'vue'
const ParentComponent = inject('ParentComponent')
const handleClick = () => {
  ParentComponent.handleChange(4)
}
</script>
<style scoped lang="scss">
.deepA-container {
  height: 200px;
  width: 200px;
  background-color: #f00;
}
</style>

 效果

点击父组件的按钮 子组件和子孙组件的数据都发生了变化

点击子孙组件的按钮 父组件的按钮发生了变化

provide/indecj可以从父组件向子孙组件传递数据,也可以从子孙组件向父组件传递数据;但是无法直接实现兄弟组件之间的传参,要是向实现兄弟组件的传参需要父组件做中间组件来实现通讯,要是有兄弟组件之间传参的需求可以eventBus 可以参看我的上一篇文章———

兄弟组件以及跨组件传参 juejin.cn/post/743627…