vue2.x学习笔记(八)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12577433.html。
列表渲染
vue提供了一个【v-for】指令用于列表渲染(循环)。
用【v-for】指令把一个数组对应为一组元素
我们可以使用【v-for】指令基于一个数组来渲染一个列表。使用【v-for】指令需要使用【item in items】形式的特殊语法,其中items是源数据数组,而item则是被迭代的数组元素的别名。
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
在【v-for】块中,我们可以访问所有父作用域的属性。此外,【v-for】指令还支持一个可选的第二参数,为当前项的索引。
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
当然了,你也可以使用【of】替代【in】作为分隔符,因为它更接近javascript迭代器的语法。
<div v-for="item of items"></div>
是不是像极了javascript中的【for-of】语法?
在【v-for】指令中使用对象
除了遍历数组之外,【v-for】指令还可以用于遍历一个对象的属性。
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
同样的,你也可以提供第二个参数作为property的名称(key键名)。
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
更多的,还可以使用第三个参数作为索引。
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
注意到遍历数组和遍历对象的差别了吗?这里有个差别就是遍历对象是支持三个参数的,分别是键值、键名和索引,而遍历数组则只支持两个参数,分别是元素和索引。
另外要注意的是,在遍历对象的时候,会按照Object.keys()的结果遍历,但是不能保证它的结果在不同的javascript引擎下都一致。
维护状态
当vue正在更新使用【v-for】指令渲染的元素列表的时候,默认采用的是【就地更新】的策略。意思就是说,如果数据项的顺序被改变,vue是不会移动dom元素来匹配数据项的顺序的,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染,类似于vue1.x的【track-by="$index"】。
这个默认模式是高效的,但是只适用于不依赖子组件状态或临时dom状态(例如表单输入值)的列表渲染输出。为了给vue一个提示,以便它能跟踪每个节点的身份,从而重用和排序现有元素,你需要为每个项提供一个唯一的key属性值。
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
建议尽可能在使用【v-for】指令的时候提供key属性,除非遍历输出的dom内容非常简单,或者是刻意依赖默认行为以获得性能上的提升。
因为key是vue识别节点的一个通用机制,并不是仅仅与【v-for】指令有特别关联。事实上,其还有一些别的用途,在之后的学习中会再次得到更多的了解。
此外,官方文档特别标注了,不要使用对象或数组之类的非基本类型值作为【v-for】指令的key,请用字符串或数值类型的值,否则可能导致意外的问题。
在【v-for】指令中的使用值范围
【v-for】指令也可以接受整数,在这种情况下,它会把模板重复对应次数。
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
其实就是一个固定次数的循环。
在<template>上使用【v-for】指令
类似于【v-if】,你也可以利用带有【v-for】指令的<template>来循环渲染一段包含多个元素的内容,相当于循环分组。
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
因为<template>是vue模板的语法,所以并不会被渲染到最终的输出结果中。
【v-for】指令和【v-if】指令一同使用
当【v-if】指令与【v-for】指令一起使用的时候,【v-for】指令会拥有比【v-if】更高的优先级,这样的机制意味着,【v-if】指令将分别重复运行于每个【v-for】指令循环中。当你只想为部分项渲染节点的时候,这种优先级的机制会十分有用。
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
以上的代码将只会渲染出未完成的todo。
但是如果你的目的是有条件地跳过循环的执行,则需要将【v-if】指令置于外层元素(或者<template>)上。
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>
总结就是,将【v-if】和【v-for】指令放在同一个元素中,相当于在循环中写if,而将【v-if】提在【v-for】指令外层,则相当于在if中写循环。
在组件使用【v-for】指令
在自定义的组件上,可以像任何普通元素一样使用【v-for】指令。
<my-component v-for="item in items" :key="item.id"></my-component>
在2.2.0+的版本,当在组件上使用【v-for】指令的时候,key是必须的,目的是使每个组件实例能独立被渲染。
在上面的例子中,并没有自动传递任何数据到组件中,这是因为组件拥有着自己的独立作用域。为了能够把迭代的数据传递到组件中,我们必须使用prop手动将数据传到组件中。
<my-component
v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id"></my-component>
不自动将item注入到组件中的原因是,这样做会使得组件与【v-for】指令的运作紧密耦合,不符合组件设计的初衷。明确组件数据的来源能够保证组件是一个独立的整体,从而使得组件能够在其他场合重复使用。
来看一个简单的todo列表的完整例子:
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="E.g. Feed the cat">
<button>Add</button>
</form>
<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>
Vue.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\
',
props: ['title']
}) new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [
{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function () {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})
注意这里的【is="todo-item"】属性,这样的写法和【<todo-item></todo-item>】的写法效果是一样的,但是可以避开一些潜在的浏览器解析错误。因为在<ul>元素里只有<li>元素会被看作有效内容,这样的写法就相当于给组件套模板,将组件里定义的<li>元素套到页面的<li>元素上。简单的理解就是规范组件的套用从而避免浏览器解析组件出错,因此这种写法在使用dom模板的时候是十分必要的。
"我还是很喜欢你,像仲夏流萤四起,弦月沉西。"
最新文章
- thwen 缓动框架
- PyInstaller 安装方法 及简单的编译exe (python3)
- 【BZOJ-3667】Rabin_Miller算法 随机化判素数
- MANIFEST.INF!JAR规范中
- 全情投入是做好工作的基础——Leo鉴书39
- Android应用程序内部启动Activity过程(startActivity)的源代码分析
- leetcode 3Sum Closest python
- ARM异常---一个Uart中断的触发处理过程:
- error: a label can only be part of a statement and a declaration is not a statement
- iOS核心笔记—MapKit框架-基础
- Ext.isIterable
- c# 集合的长度为什么是可变的
- PHP-FPM安装报错解决
- Python学习积累:使用help();打印多个变量;fileno()
- ApiGen安装
- js之面向对象
- 牛客网-《剑指offer》-数值的整数次方[快速幂运算]
- 【DB2】监控临时表空间使用
- 【GIS】地球经纬度和米换算(转)
- session过期情况下ajax请求不会触发重新登录的问题