目录html
首发日期:2019-01-20前端
上篇内容讲了vue
v-model能够把某个实例的数据与元素的数据绑定。这样当其中一份数据发生变化时,与之绑定的数据也会发生变化。好比:把示例中的数据(在页面中用{{}}
显示出来)与输入框的数据绑定npm
表单输入框有value这个值,在表单输入框里使用v-model会把表单输入框与实例的数据进行“智能”绑定(为何说智能,由于有些输入框的数据是value属性,有些不是)。数组
你能够用 v-model 指令在表单 <input>
、<textarea>
及<select>
元素上建立双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。浏览器
v-model 会忽略全部表单元素的 value、checked、selected 特性的初始值而老是将 Vue 实例的数据做为数据来源。若是但愿输入框有初始值,你应该在组件的 data 选项中声明初始值。app
会把单行文本输入框的value绑定到实例的数据中,由于value的数据就是单行文本输入框的数据。dom
<body> <div id="vm"> <input v-model="message" placeholder="edit me"> <p>Message is: {{ message }}</p> <input type="text" v-bind:value="message"> <!-- 不能使用普通的value=message,否则会识别不成正确的message,因此第三行用了v-bind --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ message:"hello world!" } }) </script>
会把多行文本元素内的文本绑定到实例的数据中,由于多行文本元素内的文本就是单行文本输入框的数据。函数
<body> <div id="vm"> <span>Multiline message is:</span> <p style="white-space: pre-line;">{{ message }}</p> <br> <textarea v-model="message" placeholder="add multiple lines"></textarea> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ message:"hello world!" } }) </script>
在文本区域
<textarea></textarea>
使用插值表达式{{}}
来插值并不会生效,应该用 v-model 来代替。性能
单个复选框:复选框也有value,不给定value值的时候value默认是布尔值(被勾选是true,没有勾选是false)
<body> <div id="vm"> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ checked:false } }) </script>
多个复选框:指定了value以后,实例绑定的数据是对应的value值【因为是多个复选框绑定到同一个实例上,因此这个实例数据应该是数组类型的。】
<body> <div id='example-3'> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-3', data:{ checkedNames:[] // 值为多个input的value的数组 } }) </script>
radio也有value,因此与实例绑定的数据就是value的值
<body> <div id="example-4"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <br> <span>Picked: {{ picked }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-4', data: { picked: ''// picked的值为input的value值 } }) </script>
select的值来源与子标签option。当select 的option没有value值的时候,默认绑定的数据为option元素的文本值;当有value时,默认绑定的数据为option元素的value值。
<body> <div id="example-5"> <select v-model="selected"> <option disabled value="">请选择</option> <option value ='a'>A</option> <!-- 这个用来测试有value的状况--> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-5', data: { selected: "" // selected 的值为 a/B/C } }) </script>
select框容许多选时:那么这时候实例的数据应该是一个数组,数组元素是option的文本值(无value时)或value
<body> <div id="example-5"> <select multiple style="width: 50px;" v-model="selected"> <option disabled value="">请选择</option> <option value='a'>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-5', data: { selected: [] // 全选时: [ "a", "B", "C" ] } }) </script>
在默认状况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了输入法组合文字时,这时候数据还没彻底输入到输入框中)。
你能够添加 lazy 修饰符,从而转变为使用 change 事件进行同步:
<!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg" >
若是想自动将用户的输入值转为数值类型,能够给 v-model 添加 number 修饰符:
<input v-model.number="age" type="number">
这一般颇有用,由于即便在 type="number" 时,HTML 输入元素的值也总会返回字符串。若是这个值没法被 parseFloat() 解析,则会返回原始的值。
若是要自动过滤用户输入的首尾空白字符,能够给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">
咱们平时也可使用class='xxx'或style='xxx:xxxx'来绑定样式。为何要选择转去使用Vue的样式绑定?由于在Vue中class或style也能够定义成数据,你可能会想要“发生XXX状况后,某元素变成某样式”,这个时候你须要定义“行为”来切换样式了,而这时候若是你使用Vue本身的样式切换会比较方便(由于首先你要获取某个元素的class属性,而后再从新赋值,这个操做可能须要本身定义一些dom操做)。
使用v-bind:class
来进行class绑定
格式一:传入的数据格式是{ class名: 布尔数据,.... }
,布尔数据影响class是否出如今元素的class属性中。
<div id="app"> <div v-bind:class="{ active: isActive }">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { isActive: true // 影响着active这个class是否出现 }, }) --> <!-- <style> .active { color: red; } </style> -->
格式一:传入的数据格式是对象名
,对象的数据格式是{ class名: 布尔数据,.... }
,布尔值影响class是否出如今元素的class属性中。
<div id="app"> <div v-bind:class="classObject">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { classObject: { active: true } }, }) --> <!-- <style> .active { color: red; } </style> -->
格式一:
<div id="app"> <div v-bind:class="[activeClass]">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { activeClass:'active' }, }) --> <!-- <style> .active { color: red; } </style> -->
使用v-bind:style
来进行style绑定
格式一:传入的数据格式是{ 样式名: 实例数据名(样式值), .... }
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { activeColor:'red', fontSize: 14 }, }) -->
格式二:传入的数据是一个对象,对象的数据格式是{ 样式名: 样式值, .... }
<div id="app"> <div v-bind:style="styleObject">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { styleObject: { color:'red', fontSize: "14px" } }, }) -->
传入的数据是一个数组,数组的元素是多个对象,对象的数据格式是{ 样式名: 样式值, .... }
<div id="app"> <div v-bind:style="[styleObject]">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { styleObject: { color:'red', fontSize: "14px" } }, }) -->
可使用v-on:事件类型='函数名'
来绑定事件。
<div id="app"> <button v-on:click="myclick">点击事件</button> <!-- on:后面跟事件类型 --> </div> <!-- var app = new Vue({ el: '#app', methods: { // 注意:是在methods里面定义函数 myclick:function (){ alert("message") } } }) -->
事件修饰符能够影响事件的运行,事件修饰符使用.
跟在事件类型的后面,例如:<a v-on:click.stop="doThis"></a>
。
v-on:click.prevent='myFunction'
。<body> <div id="app"> <a v-on:click.prevent='myFunction' href='#'>aaa</a> <!-- 默认状况下,点击a元素会进行跳转, 上面用#来演示,若是url多了一个#说明a的原生事件触发了, 而咱们如今用prevent来阻止了a元素原始的事件 --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', methods: { myFunction: function () { alert('haha') } } }) </script>
你可能须要监听键盘来触发事件,好比最经常使用的就是监听enter键了。
按键修饰符也使用.
跟在事件类型的后面 ,例如:<input v-on:keyup.enter="submit">
<!-- 完整语法 --> <a v-on:click="doSomething">...</a> <!-- 缩写 --> <a @click="doSomething">...</a>
Vue的指令是以v-开头的,它们各有各的左右,在前面已经介绍了很多了。如今再汇总一下。
为何要特地地说一下数组的操做呢?由于数组是很是经常使用的数据类型,而在Vue中有些数组操做并不会触发视图更新。为了确保数据是“响应式”的,因此特地讲一下这个。
下面的代码演示了使用普通数组操做方法时“响应失败”的状况:
<body> <div id="app"> <p>{{ myArray}}</p> <button @click='addValue1'>下标法添加</button> <button @click='addValue2'>push法</button> <!-- 若是你点了第一个,再点第二个,第一个的添加会在第二个的时候再成功显示 --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { myArray: [1,2,3] }, methods: { addValue1: function(){ this.myArray[1]=333 }, addValue2: function(){ this.myArray.push('999999') } } }) </script>
下面这些对数组操做的方法将会触发视图更新。
push()
:向数组末尾添加元素pop()
:从数组末尾取出一个元素shift()
:数组的第一个元素从其中删除,并返回第一个元素的值unshift()
:向数组的开头添加一个或更多元素,并返回新的长度splice()
:从数组中添加/删除项目,而后返回被删除的项目sort()
:对数组的元素进行排序reverse()
:对数组的元素进行逆序排序【官网的话】因为 JavaScript 的限制,Vue 不能检测如下变更的数组:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
为了解决第一类问题,如下两种方式均可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新:
Vue.set(vm.items, indexOfItem, newValue)
或vm.items.splice(indexOfItem, 1, newValue)
或vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可使用 splice:vm.items.splice(newLength)
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 如今修改a是响应式的 vm.b = 2 // `vm.b` 不是响应式的
<body> <div id="app"> <p>{{ numbers }}</p> <ul > <li v-for="n in evenNumbers">{{ n }}</li> </ul> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } } }) </script>
Vue 会尽量高效地渲染元素,一般会复用已有元素而不是从头开始渲染。这么作除了使 Vue 变得很是快以外,还有其它一些好处。
而由于复用问题,因此可能会致使如下问题。因为输入框被复用,因此输入框的数据残留了下来。
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template>
Vue 为你提供了一种方式来表达“这两个元素是彻底独立的,不要复用它们”。只需添加一个具备惟一值的 key 属性便可(没有key的label仍然被复用了):
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。若是数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每一个元素,而且确保它在特定索引下显示已被渲染过的每一个元素。
这个默认的模式是高效的,可是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每一个节点的身份,从而重用和从新排序现有元素,你须要为每项提供一个惟一 key 属性。理想的 key 值是每项都有的惟一 id。这个特殊的属性至关于 Vue 1.x 的 track-by ,但它的工做方式相似于一个属性,因此你须要用 v-bind 来绑定动态值 (在这里使用简写):
<div v-for="item in items" :key="item.id"> <!-- 内容 --> </div>
建议尽量在使用 v-for 时提供 key,除非遍历输出的 DOM 内容很是简单,或者是刻意依赖默认行为以获取性能上的提高,由于它是 Vue 识别节点的一个通用机制。