您的位置:首页 > 产品设计 > UI/UE

5-Vue指令之双向数据绑定 V-model

2017-07-15 15:59 1156 查看

喂你吃一口 v-model 的语法糖

1. 什么是双向绑定?

Vue框架很核心的功能就是双向的数据绑定。

双向是指:HTML 标签数据绑定到 Vue对象,另外反方向数据也是绑定的。

通俗点说就是,Vue 对象的改变会直接影响到 HTML 的标签的变化,而且标签的变化也会反过来影响 Vue 对象的属性的变化。

这样以来,就彻底变革了之前 Dom 的开发方式,之前 Dom 驱动的开发方式尤其是以 jQuery 为主的开发时代,都是 dom 变化后,触发 js 事件,然后在事件中通过 js 代码取得标签的变化,再跟后台进行交互,然后根据后台返回的结果再更新 HTML 标签,异常的繁琐。

有了 Vue 这种双向绑定,让开发人员只需要关心 json 数据的变化即可,Vue 自动映射到 HTML 上,而且HTML 的变化也会映射回 js 对象上,开发方式直接变革成了前端由数据驱动的 开发时代,远远抛弃了Dom开发主导的时代了。



v-model 指令用来在 <input> 、 <select>、 text、 checkbox、radio 等表单控件元素上创建双向数据绑定

它会根据控件类型自动选取正确的方法来更新元素

这样说有些神奇,但 v-model 本质上不过是语法糖

它负责监听用户的输入事件以更新数据,并处理一些极端的例子

语法糖

语法糖(Syntactic sugar),也译为糖衣语法,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

简单的说,语法糖就是一种便捷写法。例如:

input.map(item => item + 1);


input.map(function (item) {
return item + 1;
});


通过例子你可以看出来,语法糖的使用其实就是让我们的写的代码更简单,看起来也更容易理解

简单的说,语法糖就是一种便捷写法,例如:

input.map(item => item + 1)


它表达的意思就是

input.map( function ( item ){
return item + 1
})


通过这个例子你可以看出来,箭头函数让让我们写代码更简洁,但是达到的效果是一样的。这个箭头函数就是语法糖。

糖在不改变其所在位置的语法结构的前提下,实现了运行时的等价效果。

Vue 中有若干个“语法糖”:

v-model 语法糖

{{ }} 插值语法糖

组件注册语法糖

arr.$set 语法糖

后三种语法糖即使不深入理解,也可以直接应用, V-model 的实现原理我们深入理解后有助于更好的使用

1. 文本

<input v-model = 'message' placeholder = 'edit me'>
<p> {{message}}</p>


现在页面上有两个 message 的值的输出,这个时候你对对 input 框里的值发生改动时,下面的 message 值也发生了改变

2. 多行文本

<div id="app">
<span>文字输出到这里:</span>
<p style = 'white-space:pre-line'>{{message}}</p>
<br>
<textarea v-model = 'message' placeholer = '请在此输入文字'></textarea>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Vue 很强大!'
}
})


直接在文本区域插值 ( <textarea></textarea> ) 并实现效果,用 v-model 绑定一下,就实现了数据绑定

你应该已经发现了,我们一般通过 javascript 在组件中的 data 选项中声明初始值

v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值。因为它会选择 Vue 实例中的数据来作为具体的值

下面我们用 v-model 来做一个表单

<form  id = 'app'>

<input type="text" v-model = 'data.name'>
<span> 姓名: {{ data.name }}</span>
<br/>

<input type="radio" id='man' value = '男' v-model = 'data.gender'>
<label for="man"> 男 </label>
<input type="radio" id='male' value = '女' v-model = 'data.gender'>
<label for="male"> 女 </label>
<span> 性别: {{ data.gender }}</span>
<br/>

<input type="checkbox" id='book' value = '阅读' v-model = 'data.interest'>
<label for="book"> 阅读 </label>
<input type="checkbox" id='swim' value = '游泳' v-model = 'data.interset'>
<label for="swim"> 游泳 </label>
<input type="checkbox" id='song' value = '唱歌' v-model = 'data.interset' >
<label for="song"> 唱歌 </label>
<input type="checkbox" id = 'game' value = '玩游戏' v-model = 'data.interset'>
<label for="song"> 玩游戏 </label>

<br/>

<select v-model = 'data.identity'>
<option value="teacher" selected> 教师 </option>
<option value="doctor"> 医生 </option>
<option value="lawyer"> 律师 </option>
</select>

<span> 身份:{{ data.identity }}</span>
</form>

<script>
new Vue({
el: '#app',
data:{
data: {
name: "",
gender: "",
interest: [],
identity: ""
}
}
})


通过以上几个例子,你应该发现了 v-model 获取元素的 value 并且响应式更新 value ,它和 Angular的 ng-model 很像,但是 Vue 只是单向数据流,它只是实现了语法糖而已:

<input v-model = 'sth'/>
<input v-bind:value = 'sth' v-on:input = 'sth = $event.target.value'/>


第一行的代码其实是第二行的语法糖,然后第二行的代码还能简写成这样

<input:value = 'sth' @input = 'sth = $event.target.value'/>


input 元素本身有个 oninput 事件,是 HTML5 的新增,类似 onchang, 每当输入框内容发生变化时,就会触发 oninput ,把最新的 value 传递给sth

在给 元素添加 v-model 属性时,默认会把 value 作为元素的属性,然后把 ‘input’ 事件作为实时传递 value 的触发事件

实际上 v-model 真正的实现靠的是

v-bind:绑定响应式数据

触发 input 事件并传递数据 (核心和重点)


除了以上用法, v-model 指令后还可以添加多个参数 (number、lazy、debounce)

1. lazy

在默认情况下,v-model 在 input 事件中同步输入框的值与数据,我 们们可以添加一个 lazy 特性,从而将数据改到 change 事件中发生

使用 lazy 参数是将双向数据同步的时间节点从 input 触发改为了 change 触发,调用方式如下:

<!-- synced after "change" instead of "input" -->
<input v-model="message " lazy>
{{ message }}


我们在 input 框中输入”依然没变“,虽然触发了 input 事件,但是因为加入了 lazy 属性, message 的一直没有发生变化

2. number

当传给后端的字段类型必须是数值的时候,我们可以在 v-model 所在的控件上使用 number 指令,该指令会在用户输入被同步到model 中时将其转换为数值类型

如果原值的转换结果为 NaN,则返回原值

调用如下:

<input
b71a
v-model="age" number>


3. options

使用options参数是用于渲染一个select项的列表,调用方式如下:

<select v-model="selected" options="myOptions"></select>


其中options的参数名指向一个数组,该数组可以包括字符串或对象,对象可以是{text:”, value:”}的形式,指定了的value属性与text内容,例如:

[
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' }
]


将渲染出:

<select>
<option value="a">A</option>
<option value="b">B</option>
</select>


如果对象是{ label:”, options:[…] }的形式,则可以渲染出多个option组,如下例:

[
{ label: 'A', options: ['a', 'b']},
{ label: 'B', options: ['c', 'd']}
]


将渲染出:

<select>

<optgroup label="A">
<option value="a">a</option>
<option value="b">b</option>
</optgroup>

<optgroup label="B">
<option value="c">c</option>
<option value="d">d</option>
</optgroup>


4.debounce

使用 debounce 参数是指定一个延迟时间,延迟从按键触发到数据更新同步之间的时间,当我们的更新操作比较耗时时这个属性十分有用,例如搜索引擎在我们键入字符时发送 ajax 请求完成自动补全提示

设置一个最小的延时,在每次敲击之后延时同步输入框的值与数据

如果每次更新都要进行高耗操作,(例如:在 input 中输入内容时要随时发送 Ajax 请求),那么它较为有用。

调用如下:

<div id="app">
<input v-model= 'message' debounce = '5000' ><br/>
{{ message }}
</div>

var vm  = new Vue({
el: '#app',
data: {
message: '内容是在 5000ms 之后改变的!'
}
})


在5000秒内我们将输入框的内容情况, message 的值没有马上改变,还依然保持这之前的内容,5000ms 后内容才被清空

该指令是用来延迟同步用户输入的数据到 model 中,并不会延迟用户输入时间的执行。

所以如果要想获取变化后的数据,我们应该用 vm.$watch() 来监听数据变化,而不是在事件中获取最新数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  html vue-js