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

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

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

组件间的关系可以分为:

  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除了暴露子组件的内部方法或属性给父组件调用、调试测试外,还用于将可复用的组件内的方法暴露给外部调用;还能集成第三方库,暴露必要的实例或方法。

相关文章

用IDEA开发如何用Git快速拉取指定分支代码?

1,准备空的文件夹,git init2,关联远程仓库,git remote add origin gitlab地址3,拉取远程分支代码,git pull origin 远程分支名再用IDEA打开项目即...

使用GitLab实现CICD(gitlab配置cicd)

GitLab CI/CD 是一个内置在GitLab中的工具,用于通过持续方法进行软件开发:Continuous Integration (CI) 持续集成Continuous Delivery (C...

VIM配置整理(vim配置教程)

一、基本配色set number set showcmd set incsearch set expandtab set showcmd set history=400 set autoread se...

HTML5+眼球追踪?黑科技颠覆传统手机体验

今天,iH5工具推出一个新的神秘功能——眼动追踪,可以通过摄像头捕捉观众眼球活动!为了给大家具体演示该功能的使用,我做了一个案例,供大家参考。实际效果如下:案例比较简单,就是通过眼动功能获取视觉焦点位...

聊城职院获省赛“HTML5交互融媒体内容设计与制作”赛项一等奖

11月25日,山东省职业院校技能大赛(高职组)“HTML5交互融媒体内容设计与制作”赛项在威海海洋职业学院学院圆满结束。学校信息工程系由计算机应用技术专业学生张慧、冯媛、王海阔三名学生组成的参赛团队,...

HTML5与APP的抉择(h5与app的区别)

同为当下炙手可热的技术,围绕APP和HTML5难免少不了各种争辩。而在“互联网+”时代,许多面临转型的传统企业,也在选择转型工具时,陷入了HTML5或APP的纠结抉择之中……到底该选择HTML5还是A...