Vue中的数据绑定
本文最后更新于 2024年6月7日 下午
在Vue中数据绑定分为两种:“单向数据绑定”和“双向数据绑定”。
对于这二者的区别,我有以下的思考:
- 单向数据绑定:适用于父组件触发事件,改变自身
property
的值,进而将改变后的值通过prop
的方式传给子组件,进而使子组件的property
改变。 - 双向数据绑定:子组件触发事件,改变自身的
property
的值,需要用一种信号的方式,将触发事件与值发送出去,父组件监听这个事件并接收值,并用值改变自己的property
。
单向数据绑定
我学习Vue的过程中,第一个学到的特殊用法就是 Mustache 语法 ,但这种方法不能用于HTML attribute上,这时候就需要引入利用 v-bind
实现的 “单向数据绑定”,“单向数据绑定”很常用也很简单,主要用于绑定HTML attribute,以及接受参数。
绑定属性
1 |
|
1 |
|
接受参数
1 |
|
父组件 div
中的数据通过子组件 test-component
中 prop
选项中设置的参数 rMsg
传入子组件中。
双向数据绑定
v-model
双向数据绑定借助 v-model
指令实现,其实其本身并不是框架的功能,而是一种语法糖,依附于表单元素,在其上使用时可以实现数据的双向传递。
1 |
|
与
1 |
|
等价。本质上就是忽略所有表单元素的 value
、checked
、selected
attribute 的初始值,而将Vue实例中的数据作为表单元素的 初始值。
v-model
在内部为不同的输入元素使用不同的 property
并抛出不同的事件:
text
和textarea
元素使用value
property 和input
事件;checkbox
和radio
使用checked
property 和change
事件;select
字段将value
作为 property 并将change
作为事件。
但有些时候,这些特殊的属性我们将它们用于不同的目的,v-model
这样不分青红皂白地忽略其初始值容易与我们的想法相悖。
这时候就需要引入自定义组件的 v-model这一概念了,通过此我们可以自定义v-model
使用的 property 和 事件。
1 |
|
这段代码中子组件 Child
通过 model
选项设置了 property 和 事件,为什么选项名字叫做 model
呢?就是因为这个选项是用来设置 v-model
的。
设置之后这个组件就成为了一个自定义组件,在这个组件上使用 v-model
语法糖时, property 和 事件就都变成了我们设置的,而不是默认的。
事件触发的顺序为:
但是在我控制台打印出来的确实下图:
是我们构想的顺序不对吗?这个问题困扰了两天时间,最终在BB-fat的帮助下找到了可以接受的解释:
update
函数是在DOM元素重新渲染时被调用。我们的input
元素被包裹在子组件中,子组件又被包裹在父组件中,当我们在input
中输入时,首先会使子组件重新渲染,子组件渲染完成后然后才使父组件重新渲染。因此被update
中先打印出来的是“子组件”。
我们可以用下面的代码验证这个事实:
1 |
|
执行结果如下,验证了我们的猜想:
.sync
能达到“双向数据绑定”功能的还有 .sync
修饰符,并且咋一看下会觉得他和 v-model
没什么区别,事实也确实如此,他们的差别很小,不懂为什么要这么设计两种区别不大的功能。
v-model
1 |
|
v-bind.sync
1 |
|
我浏览了一些国内外有关这个问题的帖子:
将大家的意见总结如下:
- 同:都是一种可以实现双向数据绑定的语法糖。
- 异:
v-mdoel
一般在表单元素上使用,有默认绑定的property
和 事件;而.sync
绑定的对象是任意的。- 触发
v-mdoel
的是组件状态的改变,例如在input
元素上,change
事件发生后子组件发出信号;而.sync
触发的原因的是变量值的改变。 - 最主要的区别在于:
v-mdoel
比较单一,只能出现一次,因此只能绑定一个变量;而.sync
可以绑定多个变量,如:1
<comp :value="username" :age="userAge" @update:name="val => userName = val" @update:age="val => userAge = val" />
至于什么时候采用v-mdoel
什么时候采用.sync
?下面的话给出了建议:
Which one to use? It is a standard pattern to use property value as the key value carrier for a component. In this situation if you have value property and want to enable 2-way binding for it then use v-model. In all other cases use .sync
也就是除了“组件只有value
这一‘标准’值”的情况,其余情况都应该采用.sync
。