1. 核心规则:固定的命名约定
Vue 规定,只要你在模板中使用了 v-model:xxx,编译器就会强制 去监听一个名为 update:xxx 的事件。
当你写下:
ini
<Page v-model:page-num="query.pageNum" />
Vue 编译器在编译阶段(打包代码时)会直接把它机械地替换为:
ruby
<Page
:page-num="query.pageNum"
@update:page-num="query.pageNum = $event"
/>
所以,v-model 并不是"知道"绑定了事件,而是它自动帮你生成了 @update:page-num 这个事件绑定。
2. 如果子组件不配合会怎样?
既然 v-model 在父组件这边自动生成了 @update:page-num 的监听,那么如果子组件 Page.vue 里没有 写 emit('update:page-num', 新页码),会发生什么?
答案是:什么都不会发生,双向绑定失效。
- 父组件会一直傻等这个事件,但永远等不到。
- 子组件内部页码虽然变了,但父组件的
query.pageNum永远不会更新。
3. 本质:约定大于配置
这就像你们两个人约定好:"只要你举起右手(emit('update:page-num')),我就把手里的苹果给你(query.pageNum = $event)"。
v-model 就是那个帮你自动执行"只要你举手,我就给苹果"动作的机器人。它不需要去"猜"你在干什么,它只认你们事先约定好的动作(update:xxx)。
💡 总结
v-model本身不"知道"任何事件 ,它只是一个语法糖。- 它通过固定的命名规则 (
v-model:xxx对应@update:xxx),在编译时自动帮你把事件绑定写好了。 - 真正的数据传递,依然依赖于子组件老老实实地调用
emit('update:**', 新值)。
这就是 Vue 框架设计的精妙之处:把繁琐的底层事件绑定隐藏起来,让你用极其简洁的 v-model 就能实现双向同步!