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

Vue3开发极简入门(14):组件间通信之props、ref&defineExpose

zonemu15小时前技术文章1

组件间的关系可以分为:

  1. 父子关系。以前文的代码为例,最典型的就是App.vue与Car.vue这种,APP是父,Car是子。
  2. 祖孙关系。如果Car再引入一个子组件,这个子组件与App就是祖孙关系。
  3. 其他。比如Car和Staff。

基于以上的几种关系,组件间的通信方式有好些个实现。后面会讲解一些在开发中常见的方法。不多说,直接上代码。Father.vue:

<template>
    <div class="father">
        <h1>父组件</h1>
        运单ID:{{ order.orderId }},
        货主:{{ order.shipperName }},
        发车时间:{{ order.departTime }}
        <button @click="changeDriver">修改子组件的Driver</button>
        <h2></h2>
        <Son ref="sonRef" :order="order" :setDepartTime="getDepartTime" />
    </div>
</template>
<script lang='ts' setup name='Father'>
import Son from './Son.vue';
import { reactive, ref } from 'vue';
import { type Order } from '@/params';

const order = reactive<Order>({
    orderId: "111",
    shipperId: "222",
    shipperName: "货主A",
    departTime: "待定"
})

function getDepartTime(val: string) {
    order.departTime = val
}

const sonRef = ref()

function changeDriver() {
    sonRef.value.driver.driverName = "修改后的司机C"
}
</script>
<style scoped>
.father {
    background-color: darkseagreen;
}
</style>

Son.vue:

<template>
    <div class="son">
        <h1>子组件</h1>
        司机:{{ driver.driverName }}<br />
        发车时间:{{ order.departTime }}
        <button @click="departTime">发车上报</button>
        来自父组件的Order:
        运单ID:{{ order.orderId }},
        货主:{{ order.shipperName }}
    </div>
</template>
<script lang='ts' setup name='Son'>
import { reactive,watch } from 'vue';
import { type Order } from '@/params';
// 定义了子组件要接收的属性和方法,以及对应的类型。?代表可选
interface Props {
    order?: Order,
    setDepartTime: Function
}

//响应式Props解构,并指定父组件不传时的默认值
const {
    order = { orderId: "0", shipperId: "0", shipperName: "无" },
    setDepartTime
} = defineProps<Props>()

//调用父组件的方法
function departTime() {
    setDepartTime("2025-01-01 11:11:11."+Math.random())
}

//必须用deep:true才能侦听到变化
watch(() => order, (newVal) => {
    console.log('Order变了:', newVal);
},{deep:true})

const driver = reactive({ driverId: "AAAA", driverName: "司机B" })
// 暴露给父组件
defineExpose({ driver })
</script>
<style scoped>
.son {
    background-color: silver;
}
</style>

props的写法

  • interface如何定义看前文。
  • 本文写法适用Vue3.5+。
  • 父传子:父组件定义了响应式数据Order,以及函数getDepartTime(修改发车时间),在引入的子组件上通过<Son :order="order" :getDepartTime="getDepartTime"/>
  • 传给子组件。:order代表参数的key,="order"为定义的响应式数据(写的一样,但是要注意性质不同)。
  • 子传父:就是父组件提供了一个函数给子组件调用,注意“setDepartTime”和“getDepartTime”的写法。真正的子传父应该用$emit,这里仅展示一下可能性。

ref & defineExpose的写法

  • 子组件定义了响应式数据driver,通过defineExpose({ driver })暴露出去。
  • 除了数据,也可以暴露函数出去。
  • 父组件通过ref创建对子组件实例的引用<Son ref="sonRef"/>,然后再通过其实例(sonRef)访问子组件暴露的数据或方法。
  • 其实此方式不能称之为“子组件传数据或方法给父组件”,应该是“父组件使用子组件暴露的数据或方法”。真正子传父,应该使用事件$emit,后文再叙。
  • defineExpose除了暴露子组件的内部方法或属性给父组件调用、调试测试外,还用于将可复用的组件内的方法暴露给外部调用;还能集成第三方库,暴露必要的实例或方法。

相关文章

费用报销单填写及粘贴全攻略:避免常见错误!附费用报销管理系统

费用报销单是企业日常财务管理中的重要工具,用于记录和核销员工在工作中产生的各类费用。填写准确的费用报销单不仅能够保证财务报销流程的顺利进行,还能提高工作效率,确保公司资金的合理使用。在填写报销单时,员...

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

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

7 款最佳 Linux 桌面发行版,颜值天花板

一、elementary OS二、Deepin三、Pop!_OS四、Manjaro Linux五、KDE Neon六、Zorin OS七、Nitrux OS想必大家都知道三大常用操作系统:Linux、...

微软的Linux发行版终于加入了对XFS根文件系统的支持

当许多Linux发行版在评估新的根文件系统选项或甚至像OpenZFS这样的特性,微软内部Linux发行版到本月才开始支持XFS作为根文件系统选项。随着这个月对微软内部Linux发行版CBL-Marin...

Linux发行版Nobara更新39版本,号称“专为游戏玩家定制”

IT之家 12 月 27 日消息,Linux 发行版 Nobara 今天推出了 39 版本,主要改进了“Gamescope 合成器”,并更新了 OBS Studio、部分驱动程序及 Nautilus...

Win+Ubuntu缝合怪:第三方开发者推出“Wubuntu”Linux发行版

IT之家 2 月 26 日消息,一位第三方开发者推出了一款名为“Wubuntu”的缝合怪 Linux 发行版,系统本身基于 Ubuntu,但界面为微软 Windows 11 风格,甚至存在微软 Win...