Vue躬行记(3)——样式和表单
- 2019 年 10 月 21 日
- 筆記
Vue对DOM元素的class和style两个特性做了专门的增强,即对CSS类和内联样式做了一层封装,通过v-bind指令来处理它们,而接收的表达式既可以是简单的字符串、对象或数组,也可以是复杂的计算属性。不仅如此,Vue还为表单设计了一些语法糖,让表单处理变得尤为简单。
一、CSS类
v-bind指令与class参数配合,就能处理CSS类,并且能接收多种类型的值。
1)对象
v-bind:class可以接收一个对象,对象的属性名就是CSS类名,只有当其值是真值时,才能添加到DOM元素上,否则会被忽略。下面的<p>元素会接收数据对象中的classList,它包含两个属性warning和cur,其中cur属性保存了一个假值。
<p v-bind:class="classList">strick</p> <script> var vm = new Vue({ data: { classList: { warning: true, cur: "" } } }); </script>
渲染出的<p>元素如下所示,不包含cur类。
<p class="warning">strick</p>
此外,v-bind:class可简写成:class,并且能与普通的class特性共存,如下所示。
<p :class="classList" class="size">strick</p>
2)数组
当v-bind:class接收一个数组时,其元素既可以是CSS类名,也可以是对象,格式与之前相同,如下所示。
<p :class="[classList, cur]">strick</p> <script> var vm = new Vue({ data: { classList: { warning: true }, cur: "cur" } }); </script>
二、内联样式
v-bind指令与style参数配合,就能避免通过字符串拼接的方式来处理内联样式,并且也能接收多种类型的值。
1)对象
v-bind:style可以接收一个对象,对象的属性名有两种命名方式:驼峰式和连字符分隔式,第二种就是层叠样式表中的CSS属性的命名方式。下面的<p>元素会接收数据对象中的cssObj,其属性采用了两种命名方式。
<p :style="cssObj">strick</p> <script> var vm = new Vue({ data: { cssObj: { "fontSize": "30px", "line-height": 2 } } }); </script>
渲染出的<p>元素如下所示。
<p style="font-size: 30px; line-height: 2;">strick</p>
Vue允许为属性赋一个包含多个值的数组(即多重值),可让浏览器选择支持的属性,例如定义不同阶段的伸缩盒样式,如下所示。
<p :style="{display: ['-webkit-box', '-ms-flexbox', 'flex']}">strick</p>
2)数组
当v-bind:style接收一个数组时,其元素就是样式对象,并且如果出现同名的CSS属性,那么后面的会覆盖前面的。例如下面的cssObj1和cssObj2两个对象都包含line-height属性,而最终渲染出的值为1.5。
<p :style="[cssObj1, cssObj2]">strick</p> <script> var vm = new Vue({ data: { cssObj1: { "fontSize": "30px", "line-height": 2 }, cssObj2: { "line-height": 1.5 } } }); </script>
3)浏览器前缀
Vue会自动侦测浏览器样式的兼容性,并根据需要为CSS属性(例如border-radius、transform等)添加相应的浏览器前缀。
下面的代码摘自Vue.js,其中camelize()函数可将连字符分隔式的字符串转换成驼峰式的字符串;vendorNames变量记录了三种浏览器前缀;normalize()函数会判断传入的属性是否存在于<div>元素的style属性中,如果不存在,就为其添加浏览器前缀,而之所以单独处理filter属性是因为Chrome的一个bug,虽然Chrome只支持-webkit-filter属性,但是style属性中保存的却是无前缀的filter。
var camelizeRE = /-(w)/g; var camelize = cached(function(str) { return str.replace(camelizeRE, function(_, c) { return c ? c.toUpperCase() : ""; }); }); var vendorNames = ["Webkit", "Moz", "ms"]; var emptyStyle; var normalize = cached(function(prop) { emptyStyle = emptyStyle || document.createElement("div").style; prop = camelize(prop); if (prop !== "filter" && prop in emptyStyle) { return prop; } var capName = prop.charAt(0).toUpperCase() + prop.slice(1); for (var i = 0; i < vendorNames.length; i++) { var name = vendorNames[i] + capName; if (name in emptyStyle) { return name; } } });
三、表单
Vue提供了v-model指令,可在表单控件上实现双向数据绑定,即修改控件的值,也会自动更新Vue实例中所对应的数据对象的属性,反之亦然。
1)v-model
下面用一个示例来演示v-model指令的用法,文本框的初始值是“strick”,当修改<input>元素中的值时,<p>元素的文本也会随之更新。
<input type="text" v-model="name"/> <p>{{name}}</p> <script> var vm = new Vue({ data: { name: "strick" } }); </script>
而如果在控制台执行下面这条赋值语句,那么就会更新<input>元素中的值,其实这就是Vue的双向数据绑定所起的作用。
vm.name = "freedom";
在使用v-model指令时需要注意,表单控件的初始值得声明在数据对象的属性中,而不是value、checked或selected这些特性中。还是以之前的文本框为例,添加了一个value特性,如下所示,渲染出的控件值将是“strick”,而不是“init”。
<input type="text" v-model="name" value="init"/>
v-model本质上是个语法糖,它在内部会监听表单控件相关特性的变化,并触发相应的事件,其对应关系如表4所示。
表4 v-model指令内部的对应关系
表单控件 | 监听特性 | 触发事件 |
文本框(单行和多行) | value | input |
单选框和复选框 | checked | change |
选择框 | <option>子元素中的value | change |
2)表单控件
将v-model指令作用于表单控件时,其初始值常用的类型会有所不同,如下所示。
var vm = new Vue({ data: { name: "", //文本框(单行和多行) checked: true, //一个复选框 names: [], //多个复选框 color: "", //单选框 selected: "", //选择框(单选) selecteds: [] //选择框(多选) } });
当只使用一个复选框时,v-model指令可绑定一个布尔值;而当使用多个复选框时,v-model指令适合绑定数组,如下所示。
<input type="checkbox" v-model="checked" /> <input type="checkbox" value="strick" v-model="names"/> <input type="checkbox" value="freedom" v-model="names"/>
单选框与复选框不同,由于它只能选中一个值,因此不适合绑定数组,如下所示。
<input type="radio" value="red" v-model="color"/> <input type="radio" value="black" v-model="color"/>
选择框的multiple特性能控制其是否多选,而这也会决定是否需要绑定数组,如下所示。
<select v-model="selected"> <option value="1">strick</option> <option value="2">freedom</option> </select> <select v-model="selecteds" multiple> <option value="1">strick</option> <option value="2">freedom</option> </select>
3)值绑定
单选框、复选框和选择框的值原先只能是字符串或布尔值,而通过v-bind指令就能让它们绑定任意类型的值,如下所示,为两个单选框的value特性绑定了一个对象。当选中其中一个按钮时,color属性的值就会更新成绑定的对象。
<input type="radio" v-model="color" :value="{digit: 1}" /> <input type="radio" v-model="color" :value="{digit: 2}" />
复选框包含两个特殊的特性:true-value和false-value(如下代码所示),当将其选中时,toggle属性会更新为yes属性的值,否则更新为no属性的值。
<input type="checkbox" v-model="toggle" :true-value="yes" :false-value="no" /> <script> var vm = new Vue({ data: { toggle: 1, yes: 1, no: 0 } }); </script>
4)修饰符
Vue为v-model指令提供了3个修饰符,如下所列,每个修饰符后面都给出了相应的示例。
(1).lazy修饰符能将同步输入值的事件从input替换成change,以下面的文本框为例,只有当修改其值并失去焦点时,才会更新数据对象的name属性。
<input type="text" v-model.lazy="name" />
(2).number修饰符能让输入值自动转换成数字,常与number类型的文本框配合使用。
<input type="number" v-model.number="age" />
(3).trim修饰符能过滤输入值的首尾空格。
<input type="text" v-model.trim="school" />