目录
遍历数组
遍历对象
使用值范围
组件的“就地复用”原则
源码
<!-- 一般遍历数组 -->
<li v-for="item in items">{{ item.message }}</li>
<!-- 使用数组中的索引 -->
<li v-for="(item,index) in items">{{index}} {{ item.message }}</li>
遍历一个数组时,第二个参数是当起项的零起索引值,一般用这个参数做为key。
除了使用for in,还可以使用for of。以of代替in,在数组遍历与对象遍历中是通用的。
<!-- 使用 of -->
<li v-for="(item,index) of items">{{index}} {{ item.message }}</li>
<!-- 遍历对象 -->
<li v-for="(value,name,index) of object">{{ index }}. {{ name }}: {{ value }}</li>
如果是遍历对象,除了当前项的值、键名(相当于数组的索引),还有一个当前项在遍历列表所处的位置,也是零起步计算。
<!-- 使用值范围 -->
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
这纯粹是一个语法糖了,当被遍历的对象是一个数字时,相当于重复渲染n遍。
官档上有这么一段语:
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这种方式只适用于列表渲染不依赖子组件状态,或临时 DOM 状态变化。
这一段不太好理解,特别是最后一句。什么叫不依赖于子组件状态,何为临时DOM状态变化?
有开发者为此写了一个测试示例:
<h3>采用就地复用策略(vuejs默认情况)</h3>
<div v-for="(p, i) in persons">
{{p.name}}
<input type="text" />
<button @click="down(i)" v-if="i != persons.length - 1">下移</button>
</div>
<h3>不采用就地复用策略(设置key)</h3>
<div v-for="(p, i) in persons" :key="p.id">
{{p.name}}
<input type="text" />
<button @click="down(i)" v-if="i != persons.length - 1">下移</button>
</div>
data: () => ({
persons: [
{ id: 1, name: "AJ" },
{ id: 2, name: "Dandan" },
{ id: 3, name: "Yoko" }
],
}),
methods: {
down: function(i) {
if (i == this.persons.length - 1) return;
var listClone = this.persons.slice();
var one = listClone[i];
listClone[i] = listClone[i + 1];
listClone[i + 1] = one;
this.persons = listClone;
}
}
运行效果:
如果没给列表项添加key,当在输入框输入内容后,单向向下移动,组件移动,数据不移动;如果设置了key,组件与数据同时移动。
以前讲过,这是由于vue源码中判断一个虚拟DOM节点是否可复用,取决于tag与key两个条件,两个都相同,得以复用;两个都不同,不复用。
有同学问,“为什么patchVnode没有覆盖之前节点的value属性呀?”,这是value属性是运行时添加的,不属于data数据源的一部分,在vue实例解析时,value属性没有参与。
为了验证这个想法,我们将源码稍修改一下,不添加key,但是给value加一个默认值:
<div v-for="(p, i) in persons">
{{p.name}}
<input :value="p.name" type="text" />
<button @click="down(i)" v-if="i != persons.length - 1">下移</button>
</div>
这时候再运行,组件下移,数据也下移了:
细心的同学会发现,当随便输入一个数字、改变输入框内容后,单击向下移动,内容又恢复了。
这是由于我们用的是:value="p.name"
单向绑定,使用v-model="p.name"
代替就可以了。
像使用:value单向绑定的input value
就属于运行时的临时DOM状态。这是官档那段话最后一句的所指。
https://git.code.tencent.com/shiqiaomarong/vue-go-rapiddev-example/tags/v202001192
vue-and-go-example/simple-vue-project/src/AboutListRender.vue