万普插件库

jQuery插件大全与特效教程

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

组件间的关系可以分为:

  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除了暴露子组件的内部方法或属性给父组件调用、调试测试外,还用于将可复用的组件内的方法暴露给外部调用;还能集成第三方库,暴露必要的实例或方法。
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言