当前位置:首页 > 技术文章 > 正文内容

Vue3开发极简入门(16):祖孙组件间通信之provide&inject

zonemu2个月前 (07-08)技术文章28

前文说了Vue的组件间关系,有父子、爷孙、其他关系。例如之前的Father、Son是父子关系,App与Son就是爷孙关系。而props的Son,与emits的Son,就是其他关系。

前文的props是父传子,emits是子传父。靠这俩,如果想实现爷孙组件间通信,比较麻烦,爷通过props到父,父通过props到子;子通过emits到父,父通过emits到爷。如果最外到最里面的组件,中间隔的N个组件,都这么过桥一下,就比较恶心了。

这种情况下,可以用provide&inject。

爷组件,Grandpa.vue:

<template>
    <div class="grandpa">
        <h1>爷组件</h1>
        司机:{{ driverName }}<br />
        发车时间:{{ departTime }}
        <Father />
    </div>
</template>
<script lang='ts' setup name='grandpa'>
import Father from './Father.vue';
import {  provide, ref, type Ref } from 'vue';

const departTime = ref('待定')
const driverName = ref('无')

function setDriver(val: string) {
    driverName.value = val
}

provide<Ref<string>>('departTime',departTime)
provide<Function>('setDriver',setDriver)

</script>
<style scoped>
.grandpa {
    background-color: aquamarine;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    height: 100%;
}
</style>

父组件,就是导入了Son.vue,其他什么代码都没有:

<template>
    <div class="father">
        <h1>父组件</h1>
        <h2>整件事情,雨我无瓜~~</h2>
        <Son />
    </div>
</template>
<script lang='ts' setup name='Father'>
import Son from './Son.vue';
</script>
<style scoped>
.father {
    background-color: darkseagreen;
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 90%;
    margin: auto;
}
</style>

孙组件:

<template>
    <div class="son">
        <h1>孙组件</h1>
        发车时间:{{ departTime }} <br>
        <button @click="letsGo">发车上报</button>
    </div>
</template>
<script lang='ts' setup name='Son'>
import { inject, type Ref, ref } from 'vue';

const departTime = inject<Ref<string>>('departTime', ref(""))
const setDriver = inject<Function>('setDriver', (params: string) => { })

function letsGo() {
    departTime.value = "2024-01-01 11:11:11." + Math.random()
    setDriver('司机A')
}
</script>
<style scoped>
.son {
    background-color: silver;
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 80%;
    margin: auto;
}
</style>

代码都很好理解,祖代组件定义的属性、Function,用

provide('key名',属性或方法)

提供出去。

后代组件用

inject('key名')

注入接收。

这里有几个要注意的:

  • 祖代提供的属性如果不是响应式数据,在后代这里被视为常数,无法修改。使用响应式数据,后代修改了,祖代也会同步变化。
  • 网上很多资料这么写:
const test=inject('test');
const testFn=inject('testFn')

但是在使用时,IDE会报类型为未知。解决方法有:

  1. 注入时给默认值:
const test=inject('test',ref('默认值'));
const testFn1=inject('testFn1',() => {});
const testFn2=inject('testFn2',(param:type) => {}
  1. 类型断言:
const test=inject('test') as Ref<string>;
const testFn=inject('testFn') as Function

这种写法就是开发人员非常确定传入的类型一定是as的这个,让TypeScript放心大胆的去用。

  • 显示指定类型信息,并加上默认值,就是本文代码的写法,这样能保持代码的类型安全性和可维护性。其实provide不用显示指定类型信息也可以,但是带上了,代码的可读性可维护性就更好了。

相关文章

2020最新门店财务收支管理系统(通用版),直接套用,自动计算

连锁企业的财务不知道怎么做各门店的收支表,不会门店汇总,别着急,看这里,今天小编和大家分享一套2020最新最新门店财务收支系统(通用版),可以快速录入,自动计算,既方便又全面!希望对大家有所帮助!(文...

Linux之父:Linux内核5.8是“我们有史以来最大的发行版之一”

Linux内核负责人Linus Torvalds对Linux内核版本5.8的第一个候选发布版本(rc1)看得出来还是挺满意的,该版本包含80万行新代码行和超过14,000个更改的文件,占内核文件检修的...

零基础开始学 Web 前端开发,有什么建议?(附视频教程)

WEB前端看似简单,其实不然,要学的知识点很多很杂,对于零基础学习前端的小伙伴来说,一份详细的前端学习知识点大纲尤为重要。下面,话不多说,直接上干货(全网最全,没有之一)。PS:文末有福利(全阶段视频...

迁移GIT仓库并带有历史提交记录(git 迁移仓库)

迁移git仓库开发在很多时候,会遇到一个问题。GIT仓库的管理,特别是仓库的迁移。我需要保留已有的历史记录,而不是重新开发,重头再来。我们可以这样做:使用--mirror模式会把本地的分支都克隆。//...

高效使用 Vim 编辑器的 10 个技巧

在 Reverb,我们使用 MacVim 来标准化开发环境,使配对更容易,并提高效率。当我开始使用 Reverb 时,我以前从未使用过 Vim。我花了几个星期才开始感到舒服,但如果没有这样的提示,可能...

web前端入门:css+html5+javascript同时学可以吗?

HTML+CSS+JS是前端基础核心知识,肯定是都要学的。在web前端中,HTML是结构标准,CSS是样式标准,JS是行为标准,三者缺一不可。说的直白点,HTML就是骨架,CSS就是皮肤,JS就是灵魂...