乐趣区

关于前端:Vue3-关于-provideinject-的用法

前言: 在前端我的项目中牵扯的最多的莫过于组件之间的传值了,除了最最罕用的 propsemit,其实在 Vue 中还额定提供了另外几种办法。明天分享一种组件之间通信的办法。


一. 场景再现

  1. 先别着急思考题目这个 api 的含意。在这里我先入手写一个比拟常见的场景。
    所对应的组件外部代码比较简单,这里我就不展现了,逻辑上就是 这三个组件层层援用。

    所对应的页面成果如下:

  2. 如上图,这是一个在我的项目中很常见的一个场景,三层嵌套的组件。(其实还有深层次的嵌套,目前咱们拿 三层嵌套 举例足矣)
  3. ok,你当初的需要是:在 爷爷组件 内须要提供一个字符串数据 “韩振方” 去提供给 儿子组件 应用。
  4. 聪慧的你必定想到了 props,废话不多说,咱们间接上手。

二. 传递 Props

  1. “我认为多浅近呢,这不就是数据 父传子 的场景吗?我间接传递 props 去实现这个需要。”
  2. 于是我会在 GrandFather.vue写下这样一段代码
  3. 接下来就该去 Father.vue 组件去接管这个数据了。于是咱们在 Father.vue 组件定义了 props 去接管这个值。

    咱们看一眼页面

    没什么问题,爸爸组件 曾经收到了。然而别忘了咱们工作还没实现呢,咱们的需要是给 儿子组件 应用,

  4. 于是咱们又连忙接着往下传递。
  5. 所以当初咱们的 Children.vue 组件的样子就变成这个样子。

    页面成果如下:

    最终咱们的 儿子组件 也的确拿到了。

  6. 写到这里你发现了一些不太对劲的中央吗?🤔
  7. 其实咱们的 爸爸组件 是齐全不须要晓得这些属性的,它仅仅只是充当了一个 传话筒 。如果这个组件单纯是这一个应用场景还好,然而一旦咱们想要在第二个中央复用 爸爸组件 的时候,咱们会发现问题就来了。咱们必须给这个 爸爸组件 提供一个叫做 message1props,然而实际上这个 message1 并不是一个 爸爸组件 外部本人应用的一个属性。
  8. 写到这里你发现了,仅仅只多传递了一层,就导致组件的复用性变得很差。这还是仅仅只嵌套了三层的场景,一旦到了第四层,你会发现事件逐步开始变得辣手起来了,如同 props 并不是一个好的抉择了。
  9. 想到这里你会开始思考,有没有更好的解决办法呢?🤔你别说,还真有,那就是咱们明天的配角,provideinject

三. provide 和 inject

  1. 首先不要死记硬背 api 的名字,作者起名字必定都是有起因的。在很多状况下咱们通过先看这两个单词的意思。
  2. 单从这两个单词的含意就大略能猜出个大略的意思,一个是 提供 某个值,另一个是去 注册 接管 这个值。
  3. 那么问题就引出来了,咱们怎么正确的应用这两个 api 呢?其实很简略,让咱们回到 爷爷组件,还原他最后的模样。
  4. 你做的仅仅只须要两步:

    或者你会诧异,就这样就行了?我明确通知你,是的,这样就行了。

  5. 接下来最初一步,去 儿子组件 接管应用就功败垂成了。

    咱们看一下页面成果:

  6. 不仅仅数据胜利拿到了,而且要害的是咱们的 爸爸组件 是干干净净的,丝毫不影响其余中央对它的援用。
  7. 咱们再回过头解说 provide 的用法。provide 承受两个参数。第一个参数须要是一个举世无双的标识(不容许和组件外部的变量重名),第二个参数就是筹备传递的值。
    你也能够这样了解,当初 爷爷组件 拿着一个喇叭在喊🎺:“谁要‘韩振方 ’,谁要‘ 韩振方’,价格便宜,仅仅须要一个‘message’”。
  8. 这时候 儿子组件 听到了这个音讯,大喊:“我要我要!!”于是它就连忙 inject 了一个“message”。

    留神: 你用于承受的变量名字是轻易起的,不须要你和后面保持一致。

  9. 爸爸组件 丝毫不想要,所以它就压根不须要 inject
  10. 并且 inject 还能够容许你有个 兜底 的行为。什么意思? 假如这个 儿子组件 在别的中央也须要复用,然而它的 爷爷组件 或者 它压根就没有爷爷组件,那么第二个参数将作为 suibian 的默认值。
  11. 咱们测试一下,咱们首先勾销了 爷爷组件 provide 行为。

    能够看到,页面正确的显示了咱们的 兜底 数据。

三. provide 的进阶用法

  1. provide 的作用远远不止提供 字符串 类型数据而已,咱们在 爷爷组件 申明一个响应式的数据试试。
  2. 让咱们看一下 儿子组件 是否能够正确的响应。

    能够看到,的确是能够的。

  3. 当初 儿子组件 长大了,它说我本人也想控制数字的增长,能够吗?爷爷组件 是很宠 孙子 的,于是又提供了一个办法给 孙子 应用。
  4. 儿子组件 真的能够本人管制吗?孩子真的长大了吗?

    咱们测试一下:

    能够看到 儿子组件 的确是 长大了 (指胜利 inject 爷爷组件 provide 的函数)

  5. 千万不要转头就忘,第二个参数是咱们的兜底行为。如果爷爷没提供函数,我就本人应用一个没有任何行为的箭头函数。仅此而已。

四. 源码

爷爷组件代码

<script lang="ts" setup>
// 这是爷爷组件
import {ref} from "vue";
import {provide} from "vue";

import Father from "./Father.vue";

const count = ref<number>(0);
function add() {count.value = count.value + 1;}

provide("message", count);
provide("messageAdd", add); // 我把 add 也同时提供给儿子组件
</script>
<template>
  <div class="w-full h-[300px] bg-[black]">
    <span class="text-white text-[20px]"> 爷爷组件 </span>
    <button @click="add">message+1</button>
    <Father />
  </div>
</template>

父亲组件代码

<script lang="ts" setup>
// 这是父亲组件
import Children from "./Children.vue";
</script>
<template>
  <div class="w-[70%] h-[270px] bg-[pink]">
    <span class="text-[black] text-[20px]"> 爸爸组件 </span>
    <span class="text-[black] text-[15px]"></span>
    <Children />
  </div>
</template>

儿子组件代码

<script lang="ts" setup>
// 这是儿子组件

import {inject} from "vue";

const suibian = inject("message", "如果爷爷没提供没有的话就用我");
const add = inject("messageAdd", () => {});
</script>
<template>
  <div class="w-[70%] h-[230px] bg-[white]">
    <span class="text-[black] text-[20px]"> 儿子组件 </span>
    <span class="text-[black] text-[10px]">{{suibian}}</span>
    <button @click="add"> 长大了,我本人 +1</button>
  </div>
</template>

五. 思考题

如果我当初 爷爷组件 父亲组件 同时提供了一个雷同的关键词的值,儿子组件 最初会应用谁的呢?

GrandFather.vue: => provide("message","爷爷组件提供的");
Father.vue: =>provide("message","父亲组件提供的")

Children.vue:=> inject("message","我应用谁的?")

退出移动版