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

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

zonemu14小时前技术文章2

前文说了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年最漂亮的7个Linux发行版(最受欢迎的linux发行版)

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言对于想学习Linux的朋友们,心中一定有疑问,哪个Linux版本比较好入门,Li...

2024年10 大 Linux 桌面发行版推荐

年已过半,现在是探究 2024 年最流行的 Linux 发行版的最佳时机。Linux 是一个开源操作系统,构建在 Linux 内核上,并集成了 GNU shell 实用程序、桌面环境、应用程序、包管理...

linux发行版-openSUSE Agama 15安装程序发布:带来多项可用性升级

openSUSE旗下仍在开发中的全新Linux安装工具Agama,于近日推出v15版本,带来了界面增强、实用新功能等一系列改进,为用户带来更顺畅的系统安装体验!界面优化:细节之处见用心新版本在本地化设...

细数5款国外热门Linux发行版(linux发行版排名网站)

Linux系统已经与我们的生活息息相关,当你用Android手机浏览这篇文章时,你就已经在使用Linux系统。当然作为编程开发最热门的系统,他还有很多专注于开发使用的版本。Fedora热门入门推荐,一...

「图解」父子组件通过 props 进行数据交互的方法

1.组件化开发,经常有这样的一个场景,就是父组件通过 Ajax 获取数据,传递给子组件,如何通过 props 进行数据交互来实现,便是本图解的重点。2.代码的结构3.具体代码 ①在父组件 data 中...

Vue3 如何实现父子组件传值?(vue父子组件传值props)

在Vue 3中,要实现父子组件传值效果主要通过props和emit两种机制来实现,下面我们就来详细介绍一下这两种机制。父组件向子组件传值propsprops是Vue组件的一种机制,主要的作用就是实现从...