Vue的数据绑定
0 Views 前端 with
本文字数:2,941 字 | 阅读时长 ≈ 12 min

Vue的数据绑定

0 Views 前端 with
本文字数:2,941 字 | 阅读时长 ≈ 12 min

本节主要讲述Vue的数据绑定

1、数据绑定

Vue.js 作为数据驱动视图的框架,我们首先要知道的就是如何将数据在视图中展示出来,传统的 Web 项目中,这一过程往往是通过后端模板引擎来进行数据和视图的渲染,但这样导致的情况是前后端语法会交杂在一起,前端 HTML 文件中需要包含后端模板引擎的语法,而且渲染完成后如果需要再次修改视图,就只能通过获取 DOM 的方法进行修改,并手动维持数据和视图的一致。而 Vue.js 的核心是一个响应式的数据绑定系统,建立绑定后,DOM 将和数据保持同步,这样就无需手动维护 DOM,使代码能够更加简洁易懂、提升效率。

1.1、语法

本小节主要介绍 Vue.js 的数据绑定语法,出现的例子会基于以下 js 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var vm = new Vue({
el: '#app',
data: {
id: 1,
index: 0,
name : 'Vue',
avatar: 'http://webfly.com.cn',
count: [1, 2, 3, 4, 5],
names: ['Vue1.0', 'Vue2.0'],
items: [{
name: 'Vue1.0',
version: '1.0'
},
{
name: 'Vue1.1',
version: '1.0'
}
]
}
});

1.1.1、文本插值

数据绑定最基础的形式就是文本插值,使用的是双大括号标签,,示例如下:

1
<span>{{ name }}</span>

Vue.js 实例 vm 中 name 属性的值将会替换 Mustache 标签中的 name,并且修改数据对象中的 name 属性,DOM 也会随之更新。在浏览器 console 中运行 vm.name = ‘Vue 1.0’,输出结果为 Hello Vue 1.0。

模板语法同时也支持单次插值,即首次赋值后再更改 vm 实例属性值不会引起 DOM 变化 采用 v-once 代替。

1
<span v-once=”name”>{{name}}</span>

1.1.2、HTML属性

Mustache 标签也同样适用于 HTML 属性中,例如:

1
<div id="id-{{id}}"></div>

Vue.js 2.0 中废弃了这种写法,用 v-bind 指令代替

1
<div v-bind:id="id"></div>

1.1.3、绑定表达式

放在 Mustache 标签内的文本内容称为绑定表达式。除了直接输出属性值之外,一段绑定表达式可以由一个简单的 JavaScript 表达式和可选的一个或多个过滤器构成。例如:

1
2
3
{{ index + 1 }} // 1
{{ index == 0 ? 'a' : 'b'}} // a
{{ name.split('').join('|') }} // V|u|e

每个绑定中只能包含单个表达式,并不支持 JavaScript 语句,否则 Vue.js 就会抛出warning 异常。并且绑定表达式里不支持正则表达式,如果需要进行复杂的转换,可以使用过滤器或者计算属性来进行处理,以下的例子即为无效的表达式:

1
2
3
{{ var a = 1 }} // 无效
{{ if (ok) { return name } }} // 无效,但可以写成 ok ? name : '' 或者 ok && name 这
样的写法

1.1.4、过滤器

Vue.js 允许在表达式后添加可选的过滤器,以管道符“|”指示。示例 :

1
{{ name | uppercase }} // VUE

Vue.js 将 name 的值传入给 uppercase 这个内置的过滤器中(本质是一个函数),返回字符串的大写值。同时也允许多个过滤器链式使用,例如:

1
{{ name | filterA | filterB }}

也允许传入多个参数,例如:

1
{{ name | filterA arg1 arg2}}

此时,filterA 将 name 的值做为第一个参数,arg1,arg2 做为第二、第三个参数传入过滤器函数中。最终函数的返回值即为输出结果。arg1,arg2 可以使用表达式,也可以加上单引号,直接传入字符串。例如:

1
{{ name.split('') | limitBy 3 1 }} // ->u,e

1.1.5、指令

Vue.js 也提供指令(Directives)这一概念,可以理解为当表达式的值发生改变时,会有些特殊行为作用到绑定的 DOM 上。指令通常会直接书写在模板的 HTML 元素中,而为了有别于普通的属性,Vue.js 指令是带有前缀的 v- 的属性。写法上来说,指令的值限定为绑定表达式,所以上述提到的 JavaScript 表达式及过滤器规则在这里也适用。

① 参数

1
<img v-bind:src="avatar" />

指令 v-bind 可以在后面带一个参数,用冒号(:)隔开,src 即为参数。此时 img 标签中的 src 会与 vm 实例中的 avatar 绑定,等同于 :

1
<img src="{{avatar}}" />

② 修饰符

修饰符(Modifiers)是以半角句号 . 开始的特殊后缀,用于表示指令应该以特殊方式绑定。

1
<button v-on:click.stop="doClick"></button>

v-on 的作用是在对应的 DOM 元素上绑定事件监听器,doClick 为函数名,而 stop 即为修饰符,作用是停止冒泡,相当于调用了 e. stopPropagation()。

1.2、计算属性

在项目开发中,我们展示的数据往往需要经过一些处理。除了在模板中绑定表达式或者利用过滤器外,Vue.js 还提供了计算属性这种方法,避免在模板中加入过重的业务逻辑,保证模板的结构清晰和可维护性。

1
2
3
<p>{{ firstName }}</p>
<p>{{ lastName }}</p>
<p>{{ fullName }}</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
var vm = new Vue({
el: '#app',
data: {
firstName: 'Gavin',
lastName: 'CLY'
},
computed: {
fullName: function() {
// this 指向 vm 实例
return this.firstName + ' ' + this.lastName
}
}
});

此时,你对 vm.firstName 和 vm.lastName 进行修改,始终会影响 vm.fullName。

1.2.1、Setter

如果说上面那个例子并没有体现出来计算属性的优势的话,那计算属性的 Setter 方法,则在更新属性时给我们带来了便利。示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var vm = new Vue({
el: '#el',
data: {  
cents: 100
}
computed: {  
price: {   
set: function(newValue) {    
this.cents = newValue * 100;   
},
   
get: function() {    
return (this.cents / 100).toFixed(2);   
}  
}
}
});

在处理商品价格的时候,后端往往会把价钱定义成以分为单位的整型,避免在处理浮点类型数据时产生的问题。而前端则需要把价钱再转成元进行展示,而且如果需要对价钱进行修改的话,则又要把输入的价格再恢复到分传给后端,很是繁琐。而在使用 Vue.js 的计算属性后,我们可以将 vm.cents 设置为后端所存的数据,计算属性 price 为前端展示和更新的数据。

1
<p>&yen;{{price}}</p> // ¥1.00

此时更改 vm.price = 2,vm.cents 会被更新为 200,在传递给后端时无需再手动转化一遍数据。

1.3、表单控件

Vue.js 中提供 v-model 的指令对表单元素进行双向数据绑定,在修改表单元素值的同时,实例 vm 中对应的属性值也同时更新,反之亦然。本小节会介绍主要 input 元素绑定v-model 后的具体用法和处理方式,示例所依赖的 js 代码如下 :

1
2
3
4
5
6
7
8
9
10
11
var vm = new Vue({
el: '#app',
data: {
message: '',
gender: '',
checked: '',
multiChecked: [],
selected: '',
multiSelected: []
}
});

1.3.1、Text

输入框示例,用户输入的内容和 vm.message 直接绑定:

1
2
<input type="text" v-model="message" />
<span>Your input is : {{ message }}</span>

1.3.2、Radio

单选框示例

1
2
3
<label><input type="radio" value="male" v-model="gender "></lable>
<label><input type="radio" value="female" v-model="gender "></lable>
<p>{{ gender }}</p>

gender 值即为选中的 radio 元素的 value 值。

1.3.3、Checkbox

Checkbox 分两种情况:单个勾选框和多个勾选框。

单个勾选框,v-model 即为布尔值,此时 input 的 value 并不影响 v-model 的值。

1
2
<input type="checkbox" v-model="checked" />
<span>checked : {{ checked }}</span>

多个勾选框,v-model 使用相同的属性名称,且属性为数组。

1
2
3
4
<label><input type="checkbox" value="1" v-model=" multiChecked">1</lable>
<label><input type="checkbox" value="2" v-model=" multiChecked">2</lable>
<label><input type="checkbox" value="3" v-model=" multiChecked">3</lable>
<p>MultiChecked: {{ multiChecked.join('|') }}</p>

1.3.4、Checkbox

同 Checkbox 元素一样,Select 也分单选和多选两种,多选的时候也需要绑定到一个数组。

单选:

1
2
3
4
5
6
<select v-model="selected">
<option selected>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>

多选:

1
2
3
4
5
6
7
<select v-model="multiSelected" multiple>
<option selected>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>MultiSelected: {{ multiSelected.join('|') }}</span>

1.3.5、绑定value

表单控件的值同样可以绑定在 Vue 实例的动态属性上,用 v-bind 实现。示例:

1.Checkbox
<input type="checkbox" v-model="checked" v-bind:true-value="a" v-bind:false-value="b">
选中:vm.checked == vm.a
  
// -> true
未选中:vm.checked == vm.b // -> true

2.Radio
<input type="radio" v-model="checked", v-bind:value="a">
选中 : vm.checked == vm.a // -> true

3.Select Options
<select v-model="selected">

<option v-bind:value="{ number: 123 }">123</option>
</select>
选中:

1.3.6、参数特性

Vue.js 为表单控件提供了一些参数,方便处理某些常规操作。

① lazy
默认情况下,v-model 在 input 事件中同步输入框值与数据,加 lazy 属性后从会改到在change 事件中同步。

1
<input v-model="query" lazy />

② number
会自动将用户输入转为 Number 类型,如果原值转换结果为 NaN 则返回原值。

1
<input v-model="age" number/>

③ debounce
debounce 为设置的最小延时,单位为 ms,即为单位时间内仅执行一次数据更新。该参数往往应用在高耗操作上,例如在更新时发出 ajax 请求返回提示信息。

不过 Vue.js 2.0 中取消了 lazy 和 number 作为参数,用修饰符(modifier)来代替 :

1
<input v-model.lazy="query" /> <input v-model.numer="age" />

新增了 trim 修饰符,去掉输入值首尾空格 :

1
<input v-model.trim="name" />

去除了 debounce 这个参数,原因是无法监测到输入新数据,但尚未同步到 vm 实例属性时这个状态。如果仍有需要,官方提供了手动实现的例子 https://jsbin.com/zefawu/3/edit?html,output。

1.4、Class与Style绑定

在开发过程中,我们经常会遇到动态添加类名或直接修改内联样式(例如 tab 切换)。class 和 style 都是 DOM 元素的 attribute,我们当然可以直接使用 v-bind 对这两个属性进行数据绑定,例如

,然后通过修改 vm.style 的值对元素样式进行修改。但这样未免过于繁琐而且容易出错,所以 Vue.js 为这两个属性单独做了增强处理,表达式的结果类型除了字符串之外,还可以是对象和数组。本小节就会对这两个属性具体的用法进行说明。

1.4.1、Class绑定

首先说明的是 class 属性,我们绑定的数据可以是对象和数组,具体的语法如下:

① 对象语法:v-bind:class 接受参数是一个对象,而且可以与普通的 class 属性共存。

1
2
<div class="tab" v-bind:calss="{'active' : active , 'unactive' : !active}">
</div>
1
2
3
4
data: {  

active: true
}

渲染结果为:

② 数组语法:v-bind:class 也接受数组作为参数。

1
<div v-bind:class="[classA, classB]"></div>
1
2
3
4
5
6
7
data: {  

classA: 'class-a',
  

classB: 'class-b'
}

渲染结果为:

也可以使用三元表达式切换数组中的 class,

。如果 vm.isB = false, 则渲染结果为

1.4.2、内联样式绑定

style 属性绑定的数据即为内联样式,同样具有对象和数组两种形式:

① 对象语法:直接绑定符合样式格式的对象。

1
<div v-bind:style="alertStyle"></div>
1
2
3
4
5
6
7
8
9
data: {
alertStyle: {  

color: 'red',
  

fontSize: '20px'
}
}

除了直接绑定对象外,也可以绑定单个属性或直接使用字符串。

1
<div v-bind:style="{ fontSize : alertStyle.fontSize, color : 'red'}"></div>

② 数组语法:v-bind:style 允许将多个样式对象绑定到统一元素上。

1
<div v-bind:style="[ styleObjectA, styleObjectB]" .></div>
May 31, 2018
May 30, 2018