Vue3+Vite 08:父子组件通信

Vue3+Vite 08:父子组件通信 一、前置准备创建并引入子组件在 Vue 中引入并使用一个组件分为两步创建子组件文件 → 父组件引入后直接使用。script setup语法下组件引入后自动注册无需额外配置。操作步骤在项目src/components文件夹下新建Child.vue文件子组件在父组件src/App.vue中引入子组件直接在模板中使用子组件src/components/Child.vuetemplate div classchild-box p我是子组件/p /div /template script setup /script style scoped .child-box { border: 1px solid #42b983; padding: 20px; margin: 20px 0; } /style父组件src/App.vuetemplate div stylepadding: 20px; h3我是父组件/h3 !-- 直接使用子组件标签 -- Child / /div /template script setup // 引入子组件 import Child from ./components/Child.vue /script运行后即可看到父子组件的层级关系后续所有通信示例都基于这个基础结构修改。二、父传子defineProps1. 作用父组件向子组件传递数据是最常用的通信方式。子组件通过defineProps声明要接收的数据父组件通过属性绑定传值。2. 基础写法简单场景下用数组声明要接收的属性名。子组件代码template div classchild-box p子组件接收的标题{{ title }}/p p子组件接收的数量{{ num }}/p /div /template script setup // 声明要接收的属性 const props defineProps([title, num]) // 脚本中访问props数据props.title /script父组件代码template div stylepadding: 20px; h3父组件/h3 !-- 静态传值直接写字符串 -- Child title静态标题 num100 / !-- 动态传值用v-bind绑定响应式数据 -- Child :titleparentTitle :numparentNum / /div /template script setup import { ref } from vue import Child from ./components/Child.vue const parentTitle ref(动态标题) const parentNum ref(200) /script3. 进阶写法项目中推荐使用对象写法支持类型校验、默认值、必填设置。script setup const props defineProps({ // 基础类型校验 title: String, // 多类型支持 num: [Number, String], // 必填 类型校验 username: { type: String, required: true }, // 带默认值 status: { type: Boolean, default: false } }) /script注意props是只读的子组件中绝对不能直接修改否则控制台会报错。如果需要修改必须通过子传父的方式通知父组件修改。三、子传父defineEmits1. 作用子组件向父组件发送消息、传递数据。子组件通过defineEmits声明要触发的事件调用emit触发事件父组件通过v-on监听事件并接收数据。2. 代码子组件代码template div classchild-box p子组件/p button clicksendToParent给父组件发消息/button /div /template script setup // 声明要触发的事件 const emit defineEmits([sendMsg]) const sendToParent () { // 触发事件第二个参数开始是要传递的数据 emit(sendMsg, 我是子组件传来的数据) } /script父组件代码template div stylepadding: 20px; h3父组件接收数据{{ receiveMsg }}/h3 !-- 监听子组件的sendMsg事件 -- Child sendMsghandleReceive / /div /template script setup import { ref } from vue import Child from ./components/Child.vue const receiveMsg ref() // 事件处理函数参数就是子组件传来的数据 const handleReceive (data) { receiveMsg.value data } /script3. 关键说明defineEmits接收数组里面是所有要触发的事件名触发事件格式emit(事件名, 参数1, 参数2...)事件名推荐使用短横线命名如send-msg和原生事件规范保持一致四、父调用子组件能力defineExpose1. 作用父组件通过ref获取子组件实例直接调用子组件的方法、访问子组件的数据。适合需要主动触发子组件行为的场景比如打开子组件弹窗、调用子组件重置方法。2. 代码子组件代码template div classchild-box p子组件计数{{ count }}/p /div /template script setup import { ref } from vue const count ref(0) const addCount () { count.value } // 主动暴露给父组件的内容未暴露的内容父组件无法访问 defineExpose({ count, addCount }) /script父组件代码template div stylepadding: 20px; h3父组件/h3 button clickcallChild调用子组件方法/button !-- 给子组件绑定ref -- Child refchildRef / /div /template script setup import { ref, onMounted } from vue import Child from ./components/Child.vue // 创建ref和模板上的ref属性名一致 const childRef ref(null) const callChild () { // 通过.value访问子组件暴露的内容 childRef.value.addCount() console.log(子组件数据, childRef.value.count) } onMounted(() { // 必须在挂载完成后才能获取到子组件实例 console.log(挂载完成子组件实例, childRef.value) }) /script3. 注意子组件必须用defineExpose主动暴露内容父组件才能访问这是 Vue3 的安全限制父组件中ref变量在setup同步执行时是null必须在onMounted及之后的阶段才能访问到实例五、总结父传子子组件用defineProps声明属性父组件通过属性绑定传值单向只读子传父子组件用defineEmits声明事件并触发父组件用事件名监听接收父调子子组件用defineExpose暴露能力父组件通过ref获取实例调用