Vue 模板语法——列表渲染(3)

93 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1. 详解 v-forkey

1.1 v-for 中的 key 的作用

在使用 v-for 进行列表渲染时,我们通常会给元素或组件绑定一个 key 属性。

这个 key 属性有什么作用呢?我们先来看下官方的解释

  • key 属性主要用做 Vue虚拟 DOM 算法的提示,以便在对比新旧节点组时辨识 VNodes
  • 如果不使用 keyVue 会使用一种算法来最小化元素的移动并且尽可能尝试就地修改/复用相同类型元素
  • 使用 key 时,它会基于 key 的顺序变化重新排列元素,并且 key 不再存在的元素将始终被移除/销毁

官方的解释对于初学者来说并不好理解,比如下面的问题:

  • 什么是新旧节点组?什么是 VNode
  • 没有 key 时,如何尝试修改和复用的?
  • key 时,如何基于 key 重新排列的?

1.2 认识 VNode

先来解释一下 VNode 的概念:

  • 因为目前我们还没有比较完整的学习组件的概念,所以我们暂时先理解 HTML 元素创建出来的 VNode
  • VNodeVirtual Node,也就是虚拟节点(其实是存在内存中的 JavaScript 对象。相对的,诸如 <html><body><div><p>DOM 节点就是真实节点);
  • 事实上,无论元素还是组件,最终在 Vue 中表示出来的都是一个个的 VNode
  • VNode 的本质就是一个 JavaScript 对象。

假设我们有以下元素:

<div class="title" style="font-size: 30px; color: red;">哈哈哈</div>

它经过 Vue 处理后会转换成一个 VNode,是一个 JavaScript 对象,主要内容如下:

const vnode = {
  type: "div",
  props: {
    class: "title",
    style: {
      "font-size": "30px",
      color: "red"
    }
  },
  children: "哈哈哈"
}

如果上面 <div> 元素中放的不是文本,而是其它多个元素,那么这多个元素又会分别创建对应的 VNode,然后组成一个 VNode 数组赋值给 <div> 元素对应的 VNode 对象的 children 属性。

创建 VNode 的代码可以在 Vue 源码的 packages/runtime-core/src/vnode.ts 文件中看到:函数 _createVNode() 会返回一个 vnode 对象,这个对象中有很多属性,包括 typepropschildren。具体的创建过程我们也可以去调试源码查看。

总之,模板里面的元素最终会转成一个一个的 VNode,再由这些 VNode 转换成真实的 DOM,然后我们才可以在浏览器页面中看到真实 DOM 呈现的内容:

image-20210725185347692.png

多了中间这一步,主要的好处是便于做多平台的渲染:我们可以利用 VNode 做服务端的渲染,也可以用 VNode 做移动端的渲染,还可以用 VNode 做浏览器的渲染。除了做跨平台,在某些情况下,使用 VNode (虚拟 DOM)还可以有更高一点的性能。