。
通过一个小例子 看一下,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