《Vuejs设计与实现》9.4 如何移动元素

251 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

上一章中,我们提到了如何判断元素是否需要移动,这一章就是如何移动元素。首先,我们需要明确一点,移动的是真实DOM而不是虚拟DOM,因为我们所有的操作其实是为了改变UI,而不是改变内存中的数据。

在我们之前设计的虚拟DOM的格式中,有一个el 里面存放着对应真实DOM的引用,我们回忆一下当我们打补丁时,有这样的操作:

const patchElement = (n1,n2)=>{
// n1 = oldNode,n2 = newNode
    const el = n2.el = n1.el
}

这里可以理解为复用,因为我们这里是移动,当移动的时候我们需要保持对DOM的引用,这样可以让新的节点也同样获得真实DOM。

具体如何找到需要移动的元素,我们可以参考我的上一节的内容9.3 找到需要移动的元素.

在我们找到需要移动的元素之后,我们就可以着手开始移动了,移动的核心代码并不复杂,我认为注意是2点

  • 判断这个dom是不是列表中第一个元素
  • 获取el.nextSibling,然后使用insertBefore直接插入到这个之前

在这里,我们并没有重新排序dom等,而是直接使用了比较新的API,这样能保证比较高的效率。

如果按照我的水平,我可能会先cloneNode,清除innerHTML,然后排序再插入节点。

然而vue中,明显更聪明,nextSibling直接获取了当前元素之后那个元素,然后插入那个元素之前,实现了dom的重新排序,这中间并没有涉及到innerHTML,dom的重绘也会尽可能的小,显然性能更好。

除了insertBefore,还有insertAfter等方法,都可以用了解决移动元素等问题,建议大家优先使用这些API,尽量少使用innerHTML。

大家可以扩展了解一下,同时,这几个API的兼容性也是OK的,无需考虑兼容性问题。