前言和概念
在表单输入或者选择元素上例如input,select,textarea 添加上,看上去html 标签属性的东西 v-model,在vue中叫指令,就构成了 表单的双向数据绑定,即在输入的时候js同时也获取了到数据,改变js数据的时候input的内容也会随着改变。这个就是v-model 成为vue中比较核心的特点之一
vue文档解释其实这是一个语法糖,相当于包装了一个写起来不太舒服语法,后面试着解释
文章说明本章主要记录
- v-model 基础使用
- v-model 语法糖的解释
- v-model 在组件的使用
- v-model 实现数据双向绑定
其他说明
文章内容基于webpack打包实现,单文件组件 可以参考基础打包《webpack 之vue 初级打包》
vue 版本基于2.x 因为 3.x据说 v-model的原理改为proxy模式,具体还没看
基础使用
在表单元素中加入指令 v-model,这时候vue会自动忽略 表单的一些属性,对于初学者,这个规则比较重要,因为如属性 value、checked、selected attribute,给他们加上值,并不会得到得到期待的那这样
示例:
<input value="我是一个值" v-model= 'inputValue'/>
data() {
return {
inputValue:'木子聊前端'
}
}
给 input 加上的value属性值并不会起作用,最后在运行的时候变成了如下情况
因此在使用v-model双向绑定的时候 不需要加入属性,没有作用还容易造成开发干扰,vue讲究数据驱动,把所有需要的值都放到data里面渲染
但是并不是所有的属性都不需要,v-model 需要依据property 判断事件的时候 属性就不能省掉,那么什么时候需要加什么属性,其实记住一个就行,type属性,在input标签中如果不加type属性值,默认是text; input 标签需要type确定最终的类型,v-model同样需要,最终作出不同的选择比如:
text 、textarea 元素使用 value input 事件;
checkbox 、radio 使用 checked property 和 change 事件;
select 的 change 事件。
复选框操作
因为checked 属性不起作用,因此我们要对复选框操作就通过data来实现,选中还是为选中对操作
<input type="checkbox" v-model= 'ckbox'/>
return {
ckbox:true // 默认选中
}
这个时候你会发现 ckbox 变量你赋值给 它任何字符串的值都没用。最后都变成了true或flase,
ckbox:‘ckname’ // 产生交互之后 选中变成true 否则 false
这是因为 vue 中v-model 依据类型 type=checkbox ,从而自动去绑定checked属性 change事件。因此 checked 最终作出的返回是true 和false。
然后在实际当中 这个状态显然不能满足我们对复选框对需求,比如兴趣爱好(游泳,羽毛球,看书),需要选中多个,这个也是需要使用复选框对原因,不然就单选就可以,在原始html中,我们需要多个复选框对时候,是通过 name(统一值)和value (不同值)操作
<input type="checkbox" name="like" value="游泳" />
<input type="checkbox" name="like" value="羽毛球" />
那么v-model 怎么操作?
显然也是需要value这个值保存的,但是前面已经说过,value属性在v-model中会失去作用;这里vue采用了很好对方法对v-model 对应对值定义为数组对象,就可以实现value对值可用:
<input type="checkbox" v-model= 'like' value="游泳"/>游泳
<input type="checkbox" v-model= 'like' value="羽毛球"/>羽毛球
<p>{{like}}</p>
... // 省略
like:[]
...// 省略
所有对选中就存在数组里面,就可以动态获取需要对值,同时也可以赋值默认对选中
其他情况的操作示例
单选radio
下拉操作 select 的chang事件
官网写的比较详细
https://cn.vuejs.org/v2/guide/forms.html
同时vue还为v-model 提供了修饰符,这个是什么?可以简单理解为,为输入选项进行了处理和规则校验的方法,比如 去掉输入框首尾的空格修饰符.trim
:
<input v-model.trim="msg">
当获取到 input输入内容的时候,会先执行 trim 这个修饰符的方法,然后在更新data数据
v-model 语法糖
糖一般吃起来有甜甜的味道,因此人类为了让那些比较难吃,但是必须要吃的东西,在外面抹一层糖或者是甜的东西。这样难吃的 药物或者是难以下咽的补充品,就变的好吃起来。
在代码中也是有些操作起来很不方便,还不好维护就会给他,来一层蜜,这样就好操作同时维持来功能的一致性
而 v-model 实际上就是这个糖,那么这个糖下面是什么东东?
这用代码来回答先看v-model
<input v-model= 'inputValue'/>
这层糖实际上等于
<input v-bind:value= 'inputValue' @input="inputValue=$event.target.value"/>
这两个运行效果是一模一样的。没有不同,但是v-model明显要甜一些,代码也要好看的多
去掉包装就很容易理解 v-model 在vue中的实现,
v-bind:绑定响应式数据,而输入框内容发生变化,就会触发 oninput,这个属性是html自带的,只要输入框发生变化oninput 就会触发,在vue中表现为@input,因此示例中 每次都把最新的value值给inputValue 最后通过数据绑定 就看到来v-model
理解这个很重要,因为如果需定制v-model 就会用到,比如自定义组件
在组件的使用
理解v-model 实际等于v-bind+@input
; 在来实现v-model 组件就很简单,v-model 组件简单理解为自定义来一个v-model事件语法 来操作组件的交互;
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件;
写一个select组件:说明自定义 v-model
<template>
<select v-on:change="selectFn">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</template>
<script>
export default {
name:'vselect',
model:{
prop:'dis',
event:'change'
},
props:{
dis:''
},
methods: {
selectFn ($event) {
this.$emit('change', $event.target.value);
}
},
}
</script>
引用
<vselct v-model="ckbox"></vselct>
这里 ckbox 值会通过prop 属性的名称 dis 传入,此时 触发一个change事件,从而更新ckbox 属性值,就是这么简单,当然因为v-model是语法糖还有另外一种写法
<vselct
:value='ckbox'
@change="v =>{ckbox = v}"
></vselct>
实现数据双向绑定
那么了解如何使用和自定义v-model 之后,别忘记了。vue最终是一个js,这个js是怎么实现双向绑定数据的。
其实他是 通过一个对象方法 defineProperty 进行set 和get 设置的,同时更新值操作,只是进行了比较好的优化。这里有一个手动写好的双向绑定,希望对期待了解底层原理对你有帮助
《defineProperty实现双向绑定》