Vue 双向绑定语法糖 .sync 和 v-model
sync 修饰符
是 Vue 组件“双向绑定”的语法糖
,是$emit
和$event
组合的一种简写形式。由于在 Vue 中,组件规定了不能修改props
的外部数据,但有时候,当子组件数据发生变化时,我们又需要通知父组件并传递修改后的值,且还想让代码变得简单,这时候就需要用到该修饰符。指令 v-model
的作用类似,下面会讲解。
一、 理解 sync 和 v-model
假设存在一个 text-document 的子组件,当子组件中的数据变化时,需要通知父组件更新本地数据 property,以下是需求实现的伪代码:
子组件通过 $emit 方法,调用 EventBus
中的函数,生成一个自定义事件并通知父组件该事件被触发了,并传递一个参数 newTitle 给父组件。
this.$emit('update:data-source', newTitle) // update: data-source 可写成 update: dataSource,另外,数据名字 data-source 要与父组件保持一致。
父组件对 update:data-source 事件进行监听,并通过 $event
方法获得传递进来的参数($event = newTitle
),从而更新本地数据。很显然,sync 修饰符
是 :value
和 @自定义事件
的语法糖。
// 完整版
<text-document
v-bind:data-source="doc.title"
v-on:update:data-source="doc.title = $event"
></text-document>
// 语法糖
<text-document :data-source.sync="doc.title"></text-document> // 触发 update:data-source 事件,并读取传递进来的 newTitle 数据,doc.title 随之更改。
命令 v-model
和 sync
修饰符的功能是类似的,唯一不一样的是,sync 是通过 EvenBus 自定义一个事件,然后通知父组件,而 v-model 是直接对 input 事件
进行监听,因此, v-model 指令
可以理解为是 :value
和 @input事件
的语法糖 。input 事件:键盘、鼠标、任何输入设备的输入都会触发;change 事件:只在 input 失去焦点时触发。
// 窗口数据
<input :value="user.username" @input="$emit('input', $event.target.value)" />
// 本地数据-完整版
<input type="text" :value="user.username" @input="user.username = $event.target.value" />
// 本地数据-语法糖
<input type="text" v-model="user.username" />
二、实例:使用修饰符 sync
以下是一个实例,当子组件的数据发生变化时,同步通知父组件和传参,并使父组件的本地数据也发生变化。
// 子组件
<template>
<div class="child">
子组件 {{money}} 元
<button @click="$emit('update:money', money-1000)">
<span>点击一次花 1000 元</span>
</button>
</div>
</template>
<script>
export default {
props: ["money"]
};
</script>
<style>
.child {
border: 3px solid green;
}
</style>
// 父组件
<template>
<div class="app">
父组件 {{money}} 元
<hr>
<Child :money.sync="total"/>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
data() {
return { total: 10000 };
},
components: { Child }
};
</script>
<style>
.app {
border: 3px solid blue;
padding: 10px;
}
</style>
转载自:https://juejin.cn/post/7076314070848110606