v-model是语法糖,目的是在使用的过程中以v-model一个指令完成数据的双向绑定。以下通过Vue中的基础语法对v-model在inut和组件中的使用进行模拟,以达到用已知解释未知的目的。
1、input中使用
语法糖v-model:
new Vue({
el: "#app",
data() {
return {
msg: "hello world!"
};
},
template: `<div>
<input v-model="msg" placeholder="edit me">
<p>msg is: {{ msg }}</p>
</div>`
});
当前例子中,双向绑定指的是:数据msg引起了视图的改变,页面展示hello world!。视图input框中输入hello Vue!,也引起数据msg的改变,其值变为hello Vue!。
基础语法模拟:
new Vue({
el: "#app",
data() {
return {
msg: "hello world!"
};
},
template: `<div>
<input @input='inputEvent' :value='msg' placeholder="edit me">
<p>msg is: {{ msg }}</p>
</div>`,
methods: {
inputEvent($event) {
this.msg = $event.target.value
}
}
});
在视图input上绑定属性:value='msg',起初视图渲染展示hello world!。当视图发生改变展示为hello world!时,通过监听input中的input事件,通过this.msg = $event.target.value将input中的数据赋值给数据msg,以达到双向绑定的目的。
2、组件中使用
语法糖v-model:
const inputBox = {
template: `<input @input="$emit('input', $event.target.value)">`,
};
new Vue({
el: "#app",
template: `<div>
<input-box v-model="msg"></input-box>
<p>{{msg}}</p>
</div>`,
components: {
inputBox
},
data() {
return {
msg: 'hello world!'
};
}
});
例子中父组件msg的数据为hello world!,子组件中的input视图也渲染成了hello world!。当子组件中的视图input值改变为hello Vue!时,父组件中的msg也变成了hello Vue!。数据从父组件到子组件,再从子组件到父组件,即是双向数据流。
基础语法模拟:
const inputBox = {
template: `<input :value="msg" @input="$emit('input', $event.target.value)">`,
props: {
msg: String,
}
};
new Vue({
el: "#app",
template: `<div>
<input-box :msg="msg" @input="changeMsg"></input-box>
<p>{{msg}}</p>
</div>`,
components: {
inputBox
},
data() {
return {
msg: 'hello world!'
};
},
methods: {
changeMsg(v) {
this.msg = v;
}
}
});
模拟的例子中,父组件通过:msg="msg"的方式向子组件传递数据,然后子组件数据发生改变时会通过$emit的方式触发input事件,父组件通过@input=changeMsg的方式接收并修改msg的值。从父组件到子组件通过props完成,从子组件到父组件通过$emit完成,实现了数据双向流动的目的。
总结
用熟知的
prop和$emit来理解语法糖v-model将会更容易理解。