一、模拟 vue,自己写 一个数据驱动
自己写一个类似的 vue 简单的数据驱动,和 vue 源码类型, 有以下4个步骤
- 获取模板
- 创建数据
- 将数据与模板结合,得到是 HTML 元素(DOM 元素)
- 把 DOM 元素放到页面中
<body>
<!-- 1. 创建模板 -->
<div id="root">
<div>
<div>
<p>{{name}}--{{message}}</p>
</div>
</div>
<p>{{name}}</p>
<p>{{message}}</p>
</div>
<script>
// 2. 获取模板
let temNode = document.querySelector('#root');
// 3. 获取数据
let data = {
name: '姓名',
message: '消息'
}
let rKuohao = /{\{(.+?)\}\}/g;
// 4. 将数据与模板结合,生成 dom 渲染到页面中。
function compiler(template, data) {
// 获取到该模板的所有子元素,通过对子元素进行遍历,
// 文本节点通过正则来匹配{{}},对{{}}进行 data 赋值
// 元素节点通过递归来对它的子元素再次遍历
let childNodes = template.childNodes;
for(var i = 0; i<childNodes.length; i++) {
let nodeType = childNodes[i].nodeType;
if(nodeType === 3) {
let txt = childNodes[i].nodeValue;
/*
* replace 使用正则匹配一次, 函数就会被调用一次
* 函数的 第 0 个参数,表示 匹配到的内容
* 函数的 第 n 个参数,表示 正则中的第 n 组
*/
txt = txt.replace(rKuohao, (_, val) => {
let key = val;
let value = data[key];
return value;
})
childNodes[i].nodeValue = txt;
} else if (nodeType == 1) {
compiler(childNodes[i], data)
}
}
}
// 因为 dom 是引用类型, 通过 cloneNode 复制一个新的 dom, 模板 tmpNode 不会受到影响
let generateNode = temNode.cloneNode(true);
compiler(generateNode, data);
// 把生成的 dom 渲染到页面中去
root.parentNode.replaceChild(generateNode, root);
console.log(temNode, '模板')
console.log(generateNode, '新的dom')
</script>
</body>
二、以上有几个问题:
- 代码没有整合
- 只考虑了单属性,没有考虑到稍微复杂层级的属性,如 {{child.name.firstName}}
- vue 是虚拟 DOM, 我们的是真实 DOM