。
通过一个小例子 看一下,vue做了些什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<p>{{name}}</p>
<p>{{message}}</p>
</div>
<div id="a"></div>
<script>
console.log(root);
let app = new Vue({
el:"#root",
data:{
name:"哈哈",
message:"是一个男人"
}
})
console.log(root);
</script>
</body>
</html>

下面我们模仿一下vue去实现一下,插值替换的步骤:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<div>
<div>
<p>{{name}}--{{message}}</p>
</div>
</div>
<p>{{name}}</p>
<p>{{message}}</p>
</div>
<script>
let rkuohao = /\{\{(.+?)\}\}/g;//匹配双括号的正则 .+? 两面加小括号 目的是 通过正则可以把它取出来
/**
* 步骤拆解
* 1、拿到模板
* 2、拿到数据data
* 3、将数据与模板结合,得到的是html元素(DOM元素)
* 4、放到页面当中
*/
// 第1步
let tmpNode = document.querySelector("#root");
// 第2步
let data = {
name:"姓名",
message:"是一个男人"
}
// 第3步
// 递归的方法去找到需要替换的节点
// 在现在的案例中 template 是dom元素,
// 在真正的vue源码中是DOM-》字符串-》虚拟DOM(vnode)-》真正的DOM
function compiler( template,data ){
let childNodes = template.childNodes;//取出子元素
console.log(childNodes);
for(let i=0;i<childNodes.length;i++){
let type = childNodes[i].nodeType;//判断是否为文本节点 1:元素 3:文本节点
if(type === 3){
// 是文本节点
// 可以判断 里面是有有{{}}的插值
let txt = childNodes[i].nodeValue;//该属性只有文本节点才有意义
// 有没有{{}}
txt = txt.replace(rkuohao,function(_,g1){
let key = g1.trim();
let value = data[key];
// 将{{ xxx }} 替换成value
return value;
})
// 注意 现在这个txt和DOM元素是没有关系的
childNodes[i].nodeValue = txt;
}else if(type === 1){
// 是元素,需要判断是都有子元素,判断是否要插值
compiler(childNodes[i],data);//递归
}
}
}
console.log(tmpNode);//此时 插值还未被替换
let generatorNode = tmpNode.cloneNode(true);//拷贝一份模板 这里是DOM元素可以通过这样的方法 拷贝
compiler( generatorNode,data );//调用一下
console.log(generatorNode);//此时 模板中的 插值就被替换成真正的值了
// 我们此时是没有生成新的template,所以这里看到的,是直接在页面中就更新了数据,因为DOM是引用类型
// 这样做模板就没有了
// 第4步
root.parentNode.replaceChild(generatorNode,root);//替换子元素 用新的元素去替换旧的元素
// 上面的案例是一个极简的 例子 存在很大的问题
// 1、vue使用的是虚拟DOM
// 2、上面只考虑到了单属性 {{name}} 在真正的vue中会有很多这样的写法 {{child.name.firstName}}
// 3、代码没有整合 vue是用构造函数的形式整合的
</script>
</body>
</html>

。
原文:https://www.cnblogs.com/fqh123/p/13621466.html