vue2.0笔记《一》列表渲染
列表渲染
内容:
1.v-for
a.渲染数组
b.渲染对象
c.渲染一个整数
d.利用v-for 的 <template> 渲染多个元素
e.v-for with v-if
f.一个组件的 v-for
2.数组更新检测
a.变异方法
key
b.替换数组
c.注意事项
1.v-for
a.渲染数组
<template> <div id="app"> <div class='vue-demo'> item in items形式 <ul class="arry-v-for-1"> <li v-for='list in arryList'>{{list.name}}: {{list.color}}</li> </ul> <hr> (item,index) in items形式 <ul class="arry-v-for-2"> <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li> </ul> <hr> item of items形式 <ul class="arry-v-for-4"> <li v-for='list of arryList' :key="list.id">{{list.name}}: {{list.color}}</li> </ul> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }], objectList: { 'name': '小颖', 'age': 23, 'sex': '女' }, arrrys: [1,4,5,6] } }, mounted: function() { this.$nextTick(function() {}); }, methods: {} } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:

b.渲染对象
<template> <div id="app"> <div class='vue-demo'> item in items形式 <ul class="object-v-for-1"> <li v-for='value in objectList'>{{value}}</li> </ul> <hr>(item,key) in items形式 <ul class="object-v-for-2"> <li v-for='(value, key) in objectList'>{{ key }}: {{ value }}</li> </ul> <hr>(item,key,index) in items形式 <ul class="object-v-for-3"> <li v-for='(value, key, index) in objectList'>{{ key }}: {{ value }}-{{ index }}</li> </ul> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }], objectList: { 'name': '小颖', 'age': 23, 'sex': '女' }, arrrys: [1, 4, 5, 6] } }, mounted: function() { this.$nextTick(function() {}); }, methods: {} } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:

c.渲染一个整数
<template> <div id="app"> <div class='vue-demo'> <span v-for="n in 10">{{ n }} </span> <!-- <hr>负10以内的整数 <span v-for="n in -10">{{ n }} </span> --> </div> </div> </template>
页面效果:

因为vue说:v-for 也可以取整数。在这种情况下,它将重复多次模板。所以小颖在循环正10时,想着如果是负10,页面会是什么样子,然而当使用v-for循环负10的时候,页面报错,说是 “数组长度无效” 。
循环负10

<template> <div id="app"> <div class='vue-demo'> <ul> <template v-for="item in arryList"> <li>{{ item.name }} <span>{{item.color}}</span> </li> </template> </ul> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }], objectList: { 'name': '小颖', 'age': 23, 'sex': '女' }, arrrys: [1, 4, 5, 6] } }, mounted: function() { this.$nextTick(function() {}); }, methods: {} } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } span{ color: pink; } </style>
页面效果:

<template> <div id="app"> <div class='vue-demo'> <ul> <li v-for="item in 20" v-if="5<item && item<15">{{item}}</li> </ul> </div> </div> </template>
页面效果:

app.vue
<template> <div id="app"> <div id="todo-list-example"> <input v-model="newTodoText" v-on:keyup.enter="addNewTodo" placeholder="Add a todo"> <ul> <li is="todo-item" v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:title="todo.title" v-on:remove="todos.splice(index, 1)"></li> </ul> </div> </div> </template> <script> export default { name: 'app', data() { return { newTodoText: '', todos: [{ id: 1, title: 'Do the dishes', }, { id: 2, title: 'Take out the trash', }, { id: 3, title: 'Mow the lawn' } ], nextTodoId: 4 } }, mounted: function() { this.$nextTick(function() {}); }, methods: { addNewTodo: function() { this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = '' } } } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
main.js
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' Vue.config.productionTip = false Vue.component('todo-item', { template: '\ <li>\ {{ title }}\ <button v-on:click="$emit(\'remove\')">X</button>\ </li>\ ', props: ['title'] }); /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: { App } });
页面效果:
2.数组更新检测
a.变异方法
Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。
push()pop()shift()unshift()splice()sort()reverse()
在说这些数组之前,小颖想把本来在v-for中要说的 key,拿到这里来说,其实当时小颖也不知道其作用的,也是后来在执行完unshiftFun里面的代码后,再执行spliceFun代码时报错了,看了报错后,小颖才理解了官网中说的:
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的且唯一的 id。这个特殊的属性相当于 Vue 1.x 的 track-by ,但它的工作方式类似于一个属性,所以你需要用 v-bind 来绑定动态值。
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for='(list,index) in arryList' :key="list.id">{{list.name}}: {{list.color}}-{{index}}</li> </ul> <button @click='pushFun'>pushToChange</button> <button @click='popFun'>popToChange</button> <button @click='shiftFun'>shiftToChange</button> <button @click='unshiftFun'>unshiftToChange</button> <button @click='spliceFun'>spliceToChange</button> <button @click='sortFun'>sortToChange</button> <button @click='reverseFun'>reverseToChange</button> <button @click='resetFun'>Reset</button> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }] } }, mounted: function() { this.$nextTick(function() {}); }, methods: { resetFun() { this.arryList = [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }] }, pushFun() { var _a = { id: 2, name: '芒果', color: '橘色' }; this.arryList.push(_a); console.log('向数组的末尾添加一个或更多元素,并返回新的长度'); console.log(this.arryList); }, popFun() { var popValue = this.arryList.pop(); console.log('删除并返回数组的最后一个元素'); console.log(popValue); console.log(this.arryList); }, shiftFun() { var shiftValue = this.arryList.shift(); console.log('删除并返回数组的第一个元素'); console.log(shiftValue); console.log(this.arryList); }, unshiftFun() { var _a = { id: 2, name: '芒果', color: '橘色' }; this.arryList.unshift(_a); console.log('向数组的开头添加一个或更多元素,并返回新的长度'); console.log(this.arryList); }, spliceFun() { var _a = { id: 2, name: '芒果', color: '橘色' }; this.arryList.splice(1, 0, _a); console.log('删除元素,并向数组添加新元素'); console.log(this.arryList); }, sortFromId(a, b) { return a.id - b.id; }, sortFun() { this.arryList.sort(this.sortFromId); console.log('对数组的元素进行排序'); console.log(this.arryList); }, reverseFun() { this.arryList.reverse(); console.log('颠倒数组中元素的顺序'); console.log(this.arryList); } } } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:
但当将 :key="list.id" 删除后,就不会报错了。看提示可知,因为里面已经有id为2的值了,而key值绑定了id,为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。而当我执行完unshiftFun里面的代码后,再执行spliceFun时,此时arryList中已经有了id为2的值,再调用spliceFun方法
var _a = { id: 2, name: '芒果', color: '橘色' }; this.arryList.splice(1, 0, _a);
时,则key属性就不唯一了,此时会有两个id为2的值。现在大家理解key了吗?
b.替换数组
变异方法 (mutation method),顾名思义,会改变被这些方法调用的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。这些不会改变原始数组,但总是返回一个新数组。
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li> </ul> <button @click='filterFun'>filterBtn</button> <button @click='concatFun'>concatBtn</button> <button @click='sliceFun'>sliceBtn</button> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }] } }, mounted: function() { this.$nextTick(function() {}); }, methods: { filterFun() { var _a = this.arryList.filter(function(item) { return item.id > 3; }); console.log('检测数值元素,并返回符合条件所有元素的数组'); console.log(_a); console.log(this.arryList); }, concatFun() { var _a = { id: 2, name: '芒果', color: '橘色' }; var concatA = this.arryList.concat(_a); console.log('连接两个或更多的数组,并返回结果'); console.log(concatA); console.log(this.arryList); }, sliceFun() { var sliceA = this.arryList.slice(1, 2); console.log('选取数组的的一部分,并返回一个新数组'); console.log(sliceA); console.log(this.arryList); } } } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:
那有什么解决方法吗?
filterFun() { var _a = this.arryList.filter(function(item) { return item.id > 3; }); console.log('检测数值元素,并返回符合条件所有元素的数组'); // console.log(_a); // console.log(this.arryList); //解决方法: this.arryList = _a; console.log(this.arryList); }, concatFun() { var _a = { id: 2, name: '芒果', color: '橘色' }; var concatA = this.arryList.concat(_a); console.log('连接两个或更多的数组,并返回结果'); // console.log(concatA); // console.log(this.arryList); //解决方法: this.arryList = concatA; console.log(this.arryList); }, sliceFun() { var sliceA = this.arryList.slice(1, 2); console.log('选取数组的的一部分,并返回一个新数组'); // console.log(sliceA); // console.log(this.arryList); //解决方法: this.arryList = sliceA; console.log(this.arryList); }
页面效果:
c.注意事项
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue - 当你修改数组的长度时,例如:
vm.items.length = newLength
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li> </ul> <ul class="arry-v-for-3"> <li v-for='list of arrrys'>{{list}}</li> </ul> <button @click="setFun">set</button> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果', color: '红色' }, { id: 1, name: '香蕉', color: '黄色' }, { id: 4, name: '葡萄', color: '紫色' }], arrrys: [1, 4, 5, 6] } }, mounted: function() { this.$nextTick(function() {}); }, methods: { setFun() { this.arryList[1] = { id: 2, name: '芒果', color: '橘色' }; console.log(this.arryList); this.arrrys.length = 8; console.log(this.arrrys); } } } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:
解决方法:
setFun() { // //解决方法: this.$set(this.arryList, 1, { id: 2, name: '芒果', color: '橘色' }); console.log(this.arryList); //解决方法: this.arrrys.length=8; this.arrrys.splice(8); console.log(this.arrrys); }
页面效果:
3.对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for='(list,index) in arryList'>{{list.name}}-{{index}} <input type="text" v-if="list.color" v-model="list.color"> <span v-if="list.color">{{list.color}}</span> </li> </ul> <button @click="addFun">addColorPro</button> </div> </div> </template> <script> export default { name: 'app', data() { return { arryList: [{ id: 5, name: '苹果' }, { id: 1, name: '香蕉' }, { id: 4, name: '葡萄' }] } }, mounted: function() { this.$nextTick(function() {}); }, methods: { addFun() { this.arryList.forEach(function(item){ item.color='红色'; }); console.log(this.arryList); } } } </script> <style> * { margin: 0; padding: 0; } body { width: 100%; height: 100%; position: absolute; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; width: 100%; height: 100%; } </style>
页面效果:
解决方法:
将原来的addFun改为:setFun
<button @click="setFun">setColorPro</button>
setFun(){ var _this=this; this.arryList.forEach(function(item,index){ _this.$set(_this.arryList[index],'color','红色'); }); console.log(this.arryList); }
页面效果:
4.显示过滤/排序结果
有时,我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以创建返回过滤或排序数组的计算属性。
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for="n in evenNumbers">{{ n }}</li> </ul> </div> </div> </div> </template> <script> export default { name: 'app', data() { return { numbers: [1, 2, 3, 4, 5,16,20] } }, computed: { evenNumbers: function() { return this.numbers.filter(function(number) { return number % 2 === 0 }) } }, mounted: function() { this.$nextTick(function() {}); }, methods: { } } </script>
在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个 method 方法:
<template> <div id="app"> <div id="todo-list-example"> <ul class="arry-v-for-2"> <li v-for="n in even(numbers)">{{ n }}</li> </ul> </div> </div> </div> </template> <script> export default { name: 'app', data() { return { numbers: [1, 2, 3, 4, 5,12, 16, 20,21] } }, mounted: function() { this.$nextTick(function() {}); }, methods: { even: function(numbers) { return numbers.filter(function(number) { return number % 3 === 0 }) } } } </script>

浙公网安备 33010602011771号