vu e中v-model与.sync修饰符的使用差异
// 父组件 <template> <children v-model="message"></children> </template> <script> import children from "./children.vue"; export default { components: {children}, data() { return { message: "parent" }; }, watch: { // 监听message变化 message(n, o) { console.log(n, o); } } }; </script> // 子组件 <template> <h1>{{ message }}</h1> </template> <script> export default { model:{ prop: "message", // 这个字段,是指父组件设置 v-model 时,将变量值传给子组件的 msg event: "input" // 这个字段,是指父组件监听 parent-event 事件 }, props: { //此处必须定义和model的prop相同的props,因为v-model会传值给子组件 message: String }, mounted() { //这里模拟异步将msg传到父组件v-model,实现双向控制 setTimeout(_ => { this.$emit("input", "children"); //将这个值通过 emit 触发parent-event,将some传递给父组件的v-model绑定的变量 }, 1500); } }; </script>
v-model本质上就是一个语法糖。相当于为父组件绑定了一个props与更新事件,当子组件数据更新时,实质上是调用了input事件来改变父组件的值:
<template> <Children :message="message" @input="(event) => { message = event }"/> </template>
// 父组件 <template> <Children :messag.sync="message"/> </template> <script> import children from "./children.vue"; export default { components: {children}, data() { return { message: "parent" }; }, watch: { // 监听message变化 message(n, o) { console.log(n, o); } } }; </script> // 子组件 <template> <h1>{{ message }}</h1> </template> <script> export default { props: { message: String }, mounted() { setTimeout(_ => { this.$emit("update:messag", "children"); }, 1500); } }; </script>
.sync是为了实现对props的双向绑定。比如,现在有一个包含title prop的组件,可以用以下方法表达对其赋新值的意图:
this.$emit('update:title', newTitle);
然后父组件可以监听那个事件并根据需要更新一个本地的数据属性:
<template> <Children :title="title" @update:title="title = $event"/> </template>
两者差异
两者的本质都是语法糖,目的都是实现组件与外部数据的双向绑定。v-model 是 .sync的一种体现(prop是value,vm.$emit('update:input'))。.sync 比较灵活,v-model比较单一。
v-model能在像单选框、复选框等类型的输入控件中实现双向绑定,但是如果它使用在一个组件上,就无法实现双向绑定,因为从它的本质上看,它就是绑定value值,监听input事件,通过event拿到新的value并赋值给value。
总的来说,v-model倾向于“value”,是组件最终的操作结果。.sync倾向于“change”,它是父组件获取子组件状态的一种快捷方式,否则我们很可能需要用事件来判断子组件状态。是一种update操作。