一、v-model的本质是语法糖
【v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据】 -- 官方文档
什么是语法糖?
语法糖,简单来说就是【便捷写法】。
v-model是v-bind和v-on的语法糖,即,v-model算是v-bind和v-on的简洁写法。
我们以input为例说明一下v-model
<input type="text" v-model="value" />
等价于
<input type="text" :value="value" @input="value = $event.target.value"/>
等价于
<input type="text" v:bind:value="value" v-on:input="value = $event.target.value"/>
本质上来说v-model是完成事件绑定和事件监听的语法糖。
二、 v-model 仅仅是语法糖吗?(冷知识)
v-model不仅仅是语法糖,它还有副作用。
副作用如下:如果v-model绑定的是响应式对象上某个不存在的属性,那么vue会悄悄地添加这个属性,并让它响应式。
举个例子,看下面的代码
template
<el-input type="text" v-model="user.age"/>
js
export default {
data() {
return {
user: {
name: '张三',
}
}
}
}
响应式数据中没有定义user.age属性,但是template里却用了v-model绑定了user.age,猜一猜当你输入时会发生什么?
答案是:
user上会新增age属性,并且age这个属性还是响应式的。这就是【副作用】带来的效果。
三、v-model是双向绑定还是单相数据流?
3.1 v-model是双向绑定吗?
是,官方说是。
[你可以用v-model指令在表单<input>、<textarea>及<select>元素上创建双向数据绑定]。 --vue2官方文档
我们使用v-bind实现单项的数据绑定,也就是通过父组件向子组件传入数据;在这基础上,我们绑定了input事件监听,在输入的过程中通过$emit触发数据更新,从而达到双向数据绑定。
3.2 那v-model是单向数据流吗?
是的,它甚至是单相数据流的典型。
什么是单向数据流?
子组件不能改变父组件传递给它的prop属性,推荐的做法是它抛出事件,通知父组件自行改变绑定的值。而这完全符合v-model的做法。
【单相数据流】总结起来其实也就8个字:【数据向下,事件向上】。
四、在组件中使用v-model
父组件
<template>
<div class="container">
<!-- 在使用中组件 -->
<Child v-model="value"></Child>
<!-- 等同于 -->
<!-- <Child v-bind:value="value" v-on:input="input"></Child> -->
<!-- 等同于 -->
<!-- <Child :value="value" @input="input"></Child> -->
{{ value }}
</div>
</template>
<script>
// 引入组件
import Child from "./components/child";
export default {
// 注册组件
components: {
Child
},
data() {
return {
value: "22"
};
},
methods: {
input(data) {
console.log(data);
this.value = data;
}
}
};
</script>
子组件
<template>
<!-- 2. 监听 input 事件的出发 -->
<input type="text" :value="value" @input="input" />
</template>
<script>
export default {
// 1. 接受父级传递的值
props: {
value: {
type: String,
default: ""
}
},
methods: {
input(event) {
this.$emit("input", event.target.value);
}
}
};
</script>
v-model这就实现了双向数据绑定,实际上它就是通过Vue提供的事件机制。即在子组件通过$emit()触发一个事件,在父组件使用v-model即可。
完