一、代码整合及多层级属性
如下, 上一文章代码从上而下,没有进行整合,太乱,且只考虑了单属性,如下多层级属性也是必要的
<div id="root">
<p>{{info.phone}}</p>
</div>
二、更正如下
<body>
<div id="root">
<div>
<div>
<div>
<p>{{message}}-{{name}}</p>
</div>
</div>
</div>
<p>{{name}}</p>
<p>{{info.phone}}</p>
</div>
<script>
let rKuohao = /{\{(.+?)\}\}/g;
// 多层次数据返回属性值
function getValueByPath(obj, path) {
let paths = path.split('.');
let res = obj;
let prop;
while (prop = paths.shift()) {
res = res[prop];
};
return res;
}
// 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, (_, path) => {
// path 表示 data 里 key的路径,例如:info.phone
let value = getValueByPath(data, path);
return value;
})
childNodes[i].nodeValue = txt;
} else if (nodeType == 1) {
compiler(childNodes[i], data)
}
}
}
function JGVue(options) {
// 内部数据用 _ 下划线开头,内部属性用 $ 开头。
this._data = options.data;
this.el = options.el;
// 拿到当前元素。
this.$el = this._tmpNode = document.querySelector(this.el);
// 获取当前元素的父节点
this.$parentNode = this._tmpNode.parentNode;
this.render();
}
// 将模板与数据进行结合,得到 html 加到页面中去
JGVue.prototype.render = function () {
this.compiler();
}
// 编译,将模板与数据结合,得到真正的 DOM 元素
JGVue.prototype.compiler = function () {
let realDom = this._tmpNode.cloneNode(true);
compiler(realDom, this._data);
this.update(realDom);
}
// 将 DOM 元素放到页面中
JGVue.prototype.update = function (realDom) {
this.$parentNode.replaceChild(realDom, this.$el)
}
let app = new JGVue({
el: '#root',
data: {
name: '姓名',
message: '消息',
info: {
phone: '12345678901'
}
}
})
</script>
</body>
三、以上问题
- 没有转化成虚拟 DOM