子组件 ChildSimple.vue
<template>
<view>
<!-- 显示从父组件接收的数据 -->
<text>从父组件来的ID:{{ skuId }}</text>
<!-- 修改数据的按钮 -->
<button @click="changeId">修改ID</button>
<button @click="close">关闭</button>
</view>
</template>
<script setup>
// 1. 定义props - 接收父组件传过来的值
const props = defineProps({
skuId: {
type: String,
default: ''
}
})
// 2. 定义emits - 定义可以触发的事件
const emit = defineEmits(['update:skuId', 'close'])
// 3. 修改ID的方法
const changeId = () => {
// 触发 update:skuId 事件,把新值传给父组件
emit('update:skuId', 'NEW_ID_123')
}
// 4. 关闭方法
const close = () => {
// 触发 close 事件,通知父组件
emit('close')
}
</script>
父组件 ParentSimple.vue
<template>
<view>
<text>当前选中的ID:{{ currentId }}</text>
<!-- 使用 v-model: 语法绑定 -->
<ChildSimple
v-model:sku-id="currentId"
@close="handleClose"
/>
</view>
</template>
<script setup>
import { ref } from 'vue'
import ChildSimple from './ChildSimple.vue'
// 父组件的数据
const currentId = ref('INIT_ID_001')
// 处理关闭事件
const handleClose = () => {
console.log('子组件通知关闭')
// 可以在这里执行关闭弹窗等操作
}
</script>
效果
解析v-model:sku-id="currentId"
v-model:sku-id="currentId" 实际上是以下写法的语法糖:
<!-- 这样写 -->
<ChildSimple v-model:sku-id="currentId" />
<!-- 等价于 -->
<ChildSimple
:sku-id="currentId"
@update:sku-id="currentId = $event"
/>
:sku-id="currentId" - 父传子
:sku-id是v-bind:sku-id的缩写作用:将父组件的
currentId值传递给子组件的skuIdprop// 子组件中可以接收到 props: { skuId: String // 值为父组件的 currentId }数据流向:父组件 → 子组件
@update:sku-id="currentId = $event" - 子传父
@update:sku-id是v-on:update:sku-id的缩写作用:监听子组件触发的
update:skuId事件$event:子组件触发事件时传递的数据// 子组件中触发 emit('update:skuId', '新值') // '新值' 就是 $eventcurrentId = $event:将接收到的数据赋值给父组件的currentId数据流向:子组件 → 父组件
执行流程示例
// 初始状态
父组件 currentId = 'INIT_ID_001'
// 1. 父传子:子组件收到 skuId = 'INIT_ID_001'
// 2. 用户在子组件操作,选择新ID
子组件执行:emit('update:skuId', 'NEW_ID_123')
// 3. 父组件监听到事件,执行赋值
父组件执行:currentId = 'NEW_ID_123' // $event 就是 'NEW_ID_123'
// 4. 父组件数据更新,自动再次传给子组件
子组件收到新的 skuId = 'NEW_ID_123'