很多接触Vue开发不久的同学会有疑问,vue既然是单向数据流为什么会有双向绑定一说?
关于Vue数据绑定首先引用官网原话:
AngularJS 使用双向绑定,Vue 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。
官网已经说的很清楚了,在Vue中使用的是单向数据流,我们由此可以确定,Vue中的所谓的双向绑定并不是真正的双向绑定。
要想理解Vue中的所谓双向绑定首先要先弄清楚其实现原理。
例子:实现如下双向绑定的效果:
要想让上面的用户名和手机号和下面的用户名和手机号保持联动,我们首先想到的就是v-model指令。
我们先创建一个局部组件PersonalInfo.vue,并引入
<personal-info v-model="username" :phone="phone" @update:phone="val=>(phone=val)"></personal-info>
由于v-model一次只能绑定一个prop,其它的prop属性如果也要实现双向绑定的效果,我们可以使用Vue自定义事件中提供的update:myPropName的方式。
PersonalInfo.vue源码如下:
{
template: `<div>
用户名:<input :value="username" type="text" placeholder="用户名"
@input="handleUsernameChange" /><br/>
手机号:<input :value="phone" type="number" placeholder="手机号"
@input="handlePhoneChange" /><br/>
</div>`,
name: "PersonalInfo",
props: {
username: String,
phone: String,
},
methods: {
handleUsernameChange(e) {
this.$emit("input", e.target.value);
},
handlePhoneChange(e) {
this.$emit("update:phone", e.target.value);
}
}
}
下面我们试一下v-model的其它实现方式
<personal-info :username="username" @change="val=>(username=val)" :phone="phone" @update:phone="val=>(phone=val)"></personal-info>
v-model其实就是v-bind:propName加自定义事件的缩写。
此时PersonalInfo.vue需要修改为:
{
template: `<div>
用户名:<input :value="username" type="text" placeholder="用户名"
@input="handleUsernameChange" /><br/>
手机号:<input :value="phone" type="number" placeholder="手机号"
@input="handlePhoneChange" /><br/>
</div>`,
name: "PersonalInfo",
model: {
prop: 'username',
event: 'change'
},
props: {
username: String,
phone: String,
},
methods: {
handleUsernameChange(e) {
this.$emit("change", e.target.value);
},
handlePhoneChange(e) {
this.$emit("update:phone", e.target.value);
}
}
}
当输入框输入内容时会触发对应的事件回调函数,在回调函数中会再次触发父组件传递的自定事件并传值给父组件,最后在父组件回调函数中更改了Model中定义的值。
至此我们可以发现Vue中的双向绑定效果并不是真正的双向绑定,真正的双向绑定是Model<-->View,而例子中最终其实是在父组件自定义事件中重新对prop属性赋值,所以说到底我们还是通过改变Model才导致了View的更新。