vue3子组件获取并修改父组件的值
在子组件中,父组件传递来的 prop 是只读的,但是确实有修改的需求,故此做个小小研究
// 父组件使用模版:@update:xxx="dialogVisible = $event"
// 子组件使用模版
// const emits = defineEmits(['update:xxx']);
// emits('update:xxx',false)// 父组件
// :dialogVisible="dialogVisible" 向子组件传值(查询用)
// @update:dialogVisible="dialogVisible = $event" 向子组件传值(可修改)
<HelloWorld:dialogVisible="dialogVisible" @update:dialogVisible="dialogVisible = $event"
></HelloWorld>const dialogVisible = ref(false)// 子组件
// 接收父组件的数据和方法
const parentData = defineProps(['dialogVisible']);
// 接收父组件需要修改的值
const emits = defineEmits(['update:dialogVisible']);const onReset = ()=>{// 子组件执行修改父组件值emits('update:dialogVisible',false)console.log('emits','修改成功');console.log('parentData.dialogVisible 1',parentData.dialogVisible); // truenextTick(()=>{console.log('parentData.dialogVisible 2',parentData.dialogVisible); // false})setTimeout(()=>{console.log('parentData.dialogVisible 2',parentData.dialogVisible); // false},0)
}
小现象
在子组件修改 dialogVisible 值后立即从父组件再获取并打印时发现值并未立即修改
为什么会打印旧值?
-
emit 是同步的:事件触发是同步操作
-
状态更新是同步的:在父组件的事件处理函数中,状态赋值是同步的
-
prop 传递是异步的:Vue 的响应式系统更新和重新渲染是异步的
-
组件更新顺序:
-
子组件触发 emit
-
父组件同步更新自己的状态
-
父组件状态更新后,需要重新渲染才能将新值传递给子组件
-
在子组件的 emit 方法后立即打印,此时父组件尚未完成重新渲染
-
执行流程详解
-
子组件调用
emits('update:dialogVisible', false)
-
父组件的
@update:dialogVisible
处理函数执行 -
父组件同步更新
dialogVisible = false
-
此时在父组件处理函数中打印
dialogVisible
会显示false
-
但在子组件中,
props.dialogVisible
不会立即更新 -
Vue 开始异步更新过程(下一个 tick)
-
父组件重新渲染,将新值传递给子组件
-
子组件接收到新的 prop 值