vue2中的.sync修饰符用法详解
作者:小妖666
vue2的.sync修饰符用法
vue2 中实现双向数据绑定的方式有两种,一个是v-model,一个是.sync修饰符。它们的区别是一个标签或者组件上,v-model只能使用一次,而.sync修饰符可以使用多次。
在Vue中,子父组件最常用的通信方式就是通过props进行数据传递,props值只能在父组件中更新并传递给子组件,在子组件内部,是不允许改变传递进来的props值,这样做是为了保证数据单向流通。但有时候,我们会遇到一些场景,需要在子组件内部改变props属性值并更新到父组件中,这时就需要用到.sync修饰符。
看案例吧
- Father.vue
<template> <div class="hello" style="background-color: azure;"> --------------Farther-------------<br> {{ msg }} <button @click="handleMsg">changeMsg</button> <Child :msg="msg" /> </div> </template> <script> import Child from '../views/Child.vue'; export default { name: 'Father', components: { Child }, data() { return { msg: 'unchanged msg', } }, methods: { handleMsg() { this.msg = "The news of the father's change" } } } </script>
- Child.vue
<template> <div class="hello"> --------------Child----------------<br/> {{ msg }} <button @click="handleMsg">changeMsg</button> </div> </template> <script> export default { name: 'Child', props: { msg: String, }, methods: { handleMsg() { // eslint-disable-next-line vue/no-mutating-props this.msg = "The news of the child's change" } } } </script>
点击子组件的 changeMsg,消息变更,但是控制台报错
另一个环境下,也报错但是只有子组件消息变更
使用 .sync 时
- Father.vue
<Child :msg.sync="msg" />
- Child.vue
handleMsg() { this.$emit('update:msg', "The news of the child's change"); }
点击后,消息变更,并且控制台没有报错。
.sync 修饰符实现原理
.sync 修饰符也是一种语法糖,用于实现双向数据绑定,但它的实现方式与 v-model 有所不同。
- 当使用 :msg.sync="msg" 时,等价于 :msg="msg" @update:msg="msg = $event"
- 父组件使用 :msg.sync 将属性传递给子组件,并监听 update:msg 事件。子组件使用 $emit('update:msg', newValue) 来更新父组件的属性。
因为是在父组件更新值,所以就不是在子组件更新 prop 值了。
- Father.vue
<Child :msg="msg" @update:msg="childMsg"/> childMsg() { this.msg = "The news of the child's change" }
- Child.vue
<button @click="handleMsg">changeMsg</button> handleMsg() { this.$emit('update:msg', "The news of the child's change"); }
v-model 实现原理
v-model 是一种语法糖
当使用 v-model="msg" 时,等价于 :msg="msg" @input='msg=$event'
父组件使用 :msg="msg" 将属性传递给子组件,并监听 input 事件。子组件使用 props 的 value 属性接收值,并使用 $emit('input ', newValue) 来更新父组件的属性。
- Father.vue
<template> <div class="hello" style="background-color: azure;"> --------------Farther-------------<br> {{ msg }} <button @click="handleMsg">changeMsg</button> <Child v-model="msg"/> </div> </template> <script> import Child from '../views/Child.vue'; export default { name: 'Father', components: { Child }, data() { return { msg: 'unchanged msg', } }, methods: { handleMsg() { this.msg = "The news of the father's change" } } } </script>
- Child.vue
<template> <div class="hello"> --------------Child----------------<br/> {{ value }} <button @click="handleMsg">changeMsg</button> </div> </template> <script> export default { name: 'Child', props: { value: String, }, methods: { handleMsg() { this.$emit('input', "The news of the child's change"); } } } </script>
- 等同于
<Child :value="msg" @input="msg=$event"/>
在Vue2中,一个组件只能有一个v-model。 .sync 支持多个props的双向绑定
Vue3中,v-model支持参数化绑定,替代.sync的功能,例如:
<child v-model:name="userName" v-model:age="userAge" />
Vue 3中不再推荐使用.sync,转而用带参数的v-model。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。