进一步了解 Vue 在初始化视图时创建新文档的实现逻辑
发布于 2020-10-16
阅读 714
一、首先我们了解下, Vue 源码中创建新文档的函数是怎样的。
二、初识源码后,如果带着疑惑,我们则还需理解以下几个知识点。
1、document.createDocumentFragment
描述:创建一个新的空白文档片段。文档片段存在于内存中,并不在 DOM 树中。
通常的用法是:1、创建文档片段;2、将元素 append 到文档片段;3、将文档片段 append 到 DOM 树。
进一步了解 document.createDocumentFragment() 点击这里。
2、el.firstChild
描述:返回节点树中的第一个子节点,如果无子节点返回 null。
进一步了解 firstChild 点击这里。
3、el.appendChild()
描述:将一个节点添加到指定父节点的子节点列表末尾处。这应该是我们对该方法的常规记忆,但是该方法还有一个接触不多的行为:
如果需要插入的节点已经存在于当前页面的文档树中,那么 appendChild() 会先把节点从原来的位置移除,再插入到新的位置。
这里我们看下官方给出的描述:
一个节点不可能同时出现在文档的不同位置。所以,如果某个节点已经拥有父节点,在被传递给此方法后,它首先会被移除,再被插入到新的位置。若要保留已在文档中的节点,可以先使用 Node.cloneNode() 方法来为它创建一个副本,再将副本附加到目标父节点下。请注意,用 cloneNode 制作的副本不会自动保持同步。
进一步了解 appendChild() 点击这里。
三、通过对以上 Web Api 接口的初步认知可以帮助我们更好的理解 Vue 在初始化视图时的大致逻辑到底如何, 以及弄明白在 compileFragment 函数中关于
" while(firstChild = el.firstChild) {} " 、
" appendChild(firstChild) "
这些代码的运作原理。便于我们再次浏览源码时,会有更清晰的理解。下面我们再来分析下源码:
/**
* 在内存中编译新文档片段
* @param el
* @returns {DocumentFragment}
*/
compileFragment(el) {
// 1、创建空白文档存储在内存中
const f = document.createDocumentFragment();
let firstChild;
// 2、依次获取 el 的第一个节点,直至没有节点返回 null。
// 进而将 el 节点的全部内容复制到内存中,并同时移除当前页面上显示的 el 节点。
while(firstChild = el.firstChild) {
// appendChild() 将节点从原先的位置移除, 然后再插入到新文档中。
// 先用 appendChild 移除的当前节点,再用 firstChild 拿到下一个节点,通过这种方式,遍历整个目标文档
f.appendChild(firstChild)
}
return f;
}
文章主要是通过 Vue 1.0 简化后的版本进行分析,一是自己学习的总结,二是帮助大家对框架有进一步了解。通过本次的源码阅读后,发现个人对 Javascript 比较完备的认知还相差甚远。长路漫漫,我等还需快马前行呀!