概述
- 在上文 $Mount方法实现中,我们根据入口点分析了分析了HTML结构,且为每一个HTML节点构建了虚拟DOM(vnode)。本文将在此基础上实现Render渲染前的一些准备工作,为Render渲染数据打下基础。
- 后面渲染数据时,我们就能根据模板语法和vnode的关系,找到对应的数据变量,通过虚拟DOM渲染到页面中
- 目标概览

分析页面中哪些地方用了模板语法
<div id="app">
文本内容:
<span class="a">{{content}}</span>
<span class="b">{{info.school}}</span>
</div>
- 根据上文,为每一个节点构建的虚拟DOM(vnode),如下图
- 我们能看到打印出的vnode节点中,text属性值就是页面中用到模板语法

入口方法——parpaerRender
function mount(vm, el) {
const rootDom = getDom(el);
vm._vnode = contrucVNode(vm, rootDom, null);
parpaerRender(vm, vm._vnode);
}
解析vnode和模板愈发的关系
- 我们不仅需要知道页面中哪些地方用到了模板语法,还需要知道他们之间映射关系。后期我们修改数据时能够同步页面中的展示内容。
- 什么样的映射关系?:
- 单个的vnode节点中,用到了哪些模板语法
- 单个的模板语法,有哪些vnode节点用到了。
- 使用ES6中 Map对象
代码实现——parpaerRender方法
- nodeType为3,表示是以一个文本节点
- analysisTemplteString:分析模板
export function parpaerRender(vm, vnode) {
if (vnode.nodeType === 3) {
analysisTemplteString(vnode);
}
for (let i = 0; i < vnode.children.length; i++) {
parpaerRender(vm, vnode.children[i]);
}
}
代码实现——analysisTemplteString()
- 用正则表达式找到单个vnode中有哪些模板语法,形如{{xxx}}
- 有使用到模板语法的,就拿去生成对应的映射关系
function analysisTemplteString(vnode) {
console.log("-vnode--", vnode);
const template = vnode.text.match(/{{[\s|a-zA-Z0-9_.|\s]+}}/g);
if (template && template.length) {
for (let i = 0; i < template.length; i++) {
setTemplateToVNode(template[i], vnode);
setVNodeToTemplate(template[i], vnode);
}
}
}
得到映射关系
- 下图是我们得到的映射关系,templateToVNode打印结果,可以看出使用到
contnet变量的,只用一个vnode节点;VNodeToTemplat打印的结果,可以看出单个vnode节点下,使用到的模板语法

const templateToVNode = new Map();
const VNodeToTemplate = new Map();
function getTemplate(template) {
if (typeof template !== "string") return;
if (template.startsWith("{{") && template.endsWith("}}")) {
return template.substring(2, template.length - 2);
}
return "";
}
function setTemplateToVNode(template, vnode) {
const templateName = getTemplate(template);
const setVNode = templateToVNode.get(templateName);
if (setVNode) {
setVNode.push(vnode);
} else {
templateToVNode.set(templateName, [vnode]);
}
}
function setVNodeToTemplate(template, vnode) {
const setTemplate = VNodeToTemplate.get(vnode);
if (setTemplate) {
setTemplate.push(template);
} else {
VNodeToTemplate.set(vnode, [template]);
}
}