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

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

zonemu3个月前 (07-08)技术文章58

前文说了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不用显示指定类型信息也可以,但是带上了,代码的可读性可维护性就更好了。

相关文章

Ubuntu 24.10发行版登场:Linux 6.11内核、GNOME 47桌面环境

IT之家 10 月 11 日消息,Canonical 昨日发布新闻稿,正式推出代号为 Oracular Oriole 的 Ubuntu 24.10 发行版。新版在内核方面升级到最新 6.11 版本,并...

Windows 下 Git 拉 Gitlab 代码(gitlab拉项目)

读者提问:『阿常你好,Windows 下 Git 拉 Gitlab 代码的操作步骤可以分享一下吗?』阿常回答:好的,总共分为五个步骤。一、Windows 下安装 Git官网下载链接:https://g...

jenkins+gitlab 实现自动化部署(gitlab触发jenkins)

目录1、安装jdk,要记住安装路径2、安装maven,要记住安装路径3、安装git,要记住安装路径4、安装gitlab5、安装jenkins(centos7)创建安装目录下载通用war包启动和关闭Je...

Excel十大逆天函数,你都会用吗?(excel函数公式大全优秀率)

Excel十大逆天函数,不管你是新手还是老手,Excel函数都是常看常新,我们一起来学习吧!以下是函数的简要介绍:一、TextJoin函数用法:用于将多个文本字符串连接成一个字符串,并且可以指定分隔符...

vue-router是如何解析query参数呢? #前端

vue-router 中的 query 解析。1. 大家好,我是龙仔。今天来分享 vue-router 是如何解析快乐参数的,因为使用 vue 路由会传 query 参数和快乐参数,所以从 vue 的...

Vue实战篇|使用路由管理用户权限(动态路由)

权限控制是后台管理系统比较常见的需求,如果我们需要对某些页面的添加权限控制的话,那我们可以在路由管理中的权限做一些校验,没有通过权限校验的给出相应的提示或者直接跳转到报错页面。跟着我一起来学vue实战...