1.设计思路
v-model 本质上是语法糖,负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
在大部分情况下, v-model="XXX" 等价于 :value="XXX" 加上 @input="XXX = $event"
存在以下两点特殊情况:
-
vue2给组件提供了model属性,可以让用户自定义传值的prop名和更新值的事件名。 -
对于原生
html原生元素,vue干了大量『脏活儿』,在原生HTML中,需要处理的事件是$event.target.value:
textarea元素:
select下拉框:
input type='radio'单选框:
input type='checkbox'多选框:
在编程思想上,这种帮助使用者『隐藏细节』的方式叫封装。
副作用
如果 v-model 绑定的是响应式对象上某个不存在的属性,那么 vue 会悄悄地增加这个属性,并让它响应式。
<template>
<div id="app">
{{user.tel}}
<input type="text" v-model="user.tel">
</div>
</template>
<script>
export default {
name: "App",
data(){
return {
user:{
name:"小米"
}
}
}
}
</script>
这段代码会为user自动添加响应式的tel属性
双向绑定和单向数据流
子组件不能改变父组件传递给它的 prop 属性,推荐的做法是它抛出事件,通知父组件自行改变绑定的值,简而言之:『数据向下,事件向上』。
自定义组件的v-model
子组件
<!-- vue中的自定义组件中,若父组件中用v-model的话,其实相当于v-bind:value='***'并且v-on:input='***' -->
<!-- 因此子组件内部用props接收value值,用$emit触发input事件,默认传递value值和input事件是模拟v-model的默认规则
@是v-on监听事件的简写,:是v-bind绑定属性的简写-->
<!--<input type="text" class="input-v-model" :value="value" @input="inputChange" /> -->
<template lang="">
<div class="red">
<input type="text" @input="value=$event.target.value" :value="value">
{{value}}
</div>
</template>
<script>
export default {
name:"child",
props:{
value:{
type:String
}
},
methods:{
inputChange(e){
this.$emit("input",e.target.value)
}
}
}
</script>
<style>
.red{
border: 1px solid red;
}
</style>
父组件
<template>
<div id="app" class="blue">
<child v-model="childName"></child>
</div>
</template>
<script>
import Child from "./components/Child.vue"
export default {
name: "App",
components:{
Child
},
data(){
return{
childName:""
}
},
methods:{
}
}
</script>
<style>
.blue{
border: 1px solid blue;
}
</style>