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

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

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

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

相关文章

智能停车场管理系统五种收费类型设置

智能停车场管理系统五种收费类型设置  点击智能停车场管理系统收费标准设置图标,出现下图所示对话框,在这个界面里面可以对停车场系统需要使用的收费标准进行个性化设置:共有五种收费类型(标准收费类、通用标准...

7种超轻量级的Linux发行版,能够帮助你找到适合自己的操作系统

Linux是一种非常受欢迎的开源操作系统,而且有许多版本可以选择。有时候,你需要一种超轻量级的Linux发行版,它可以在资源有限的设备上运行,并且能够快速启动。本文将介绍7种超轻量级的Linux发行版...

git的几种分支模式(git分支的概念)

编写代码,是软件开发交付过程的起点,发布上线,是开发工作完成的终点。代码分支模式贯穿了开发、集成和发布的整个过程,是工程师们最亲切的小伙伴。那如何根据自身的业务特点和团队规模来选择适合的分支模式呢?本...

Java教程:GitLab在项目的环境搭建和基本的使用

gitlab-使用入门1 导读本教程主要讲解了GitLab在项目的环境搭建和基本的使用,可以帮助大家在企业中能够自主搭建GitLab服务,并且可以GitLab中的组、权限、项目自主操作GitLab简介...

Jenkins 学习笔记(jenkins要学多久)

本学习笔记参考《Jenkins 2.x实践指南》。1. Jenkins 简介#Jenkins 是一款自动化的任务执行工具。通常用于持续集成/持续交付领域。可以通过界面或Jenkinsfile告诉Jen...

HTML5最新版本介绍(“html5”)

HTML5是HTML4.01和XHTML1.0之后超文本标记语言的最新版本,由一群自由思想者设计,最终实现了多媒体支持、交互性、更智能的表单和更好的语义标注。 HTML 5不只是 HTML规范的最新...