# 文档初探(四): 列表渲染
# 使用v-for
# 对 Object 使用v-for
上面是对数组使用v-for
, 这里对 Object 使用v-for
.
# key
的作用
key
的作用是为了在 diff 算法执行时更快的找到对应的节点,提高 diff 速度. 如果在列表渲染里不用key
, 那就是不好的实践? 也不一定, 得分情况来判断. Vue 使用in-place patch
来处理改动列表数据的渲染方式: 它会直接改变 DOM 节点的属性达到效果. 比如有
它会生成五个div
节点:
[
"<div>1</div>", // id: A
"<div>2</div>", // id: B
"<div>3</div>", // id: C
"<div>4</div>", // id: D
"<div>5</div>" // id: E
];
2
3
4
5
6
7
当我们改动数据源: vm.dataList = [5,4,3,2,1]
接着 Vue 生成新的 Virtual DOM, 和旧的 Virtual DOM 进行比较, 发现它们的节点都没有变化, 于是触发默认方法(in-place patch), 把各自div
的innerText
替换为新的dataList
. 如果给每个节点加一个id
. 那么它们的id
是不变的:
[
"<div>5</div>", // id: A
"<div>4</div>", // id: B
"<div>3</div>", // id: C
"<div>2</div>", // id: D
"<div>1</div>" // id: E
];
2
3
4
5
6
7
默认方法是有局限性的, Vue 文档里这样说:
This default mode is efficient, but only suitable when your list render output does not rely on child component state or temporary DOM state (e.g. form input values).
为了解决它, 我们使用key
, 给每个列表的 item 加上一个key
属性, 相当于给每个 item 一个标识, 给上面的例子加上一个key
属性后, 它更新的方式就会发生变化:
[
"<div>5</div>", // id: E
"<div>4</div>", // id: D
"<div>3</div>", // id: C
"<div>2</div>", // id: B
"<div>1</div>" // id: A
];
2
3
4
5
6
7
Vue 直接交换了 DOM 的位置, 如果我们对数据有增删, 那么也会相应地触发 DOM 的增删节点的操作. 同时这样的操作方式也会带来性能开销比原来大的问题.
WARNING
用数组的 index 作为 key 与不用 key 是一样的, 因为在数组里删除一个数, 那么其后面的一位数会立马占位被删掉的数, 后面的也是如此, 被删数的后面的所有 item 的 index 都会发生变化.会造成 bug.
# 检测数组的改变
Vue 会检测data
里数组的变化, 一些方法会触发视图的更新,. 这些方法其实就是 JS 里会改变原数组的方法吗, 如push()
, splice()
, sort()
, reverse()
等. 所以, 对于那些不改变原数组的方法(filter()
, concat()
, slice()
)我们可以使用赋值的方式来触发视图的更新.
WARNING
由于 JS 的限制, Vue 不能检测到下面两种情况的数组改变:
- 直接设置数组的某项的值:
vm.items[indexOfItem] = newValue
- 修改数组的长度:
vm.items.length = newLength
TIP
为了解决上述的问题, 这里提供解决方法:
针对第一种情况:
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
针对第二种情况:
vm.items.splice(newLength)
# 检测对象改变
# 新增对象属性
Vue.set(object, propertyName, value)
vm.$set(object, propertyName, value)
vm.object = Object.assign({}, vm.object, { // options });
1
2
3
# v-if
& v-show
v-show
: expensive initial load, cheap togglingv-if
: cheap initial load, expensive toggling