實現 MVVM 類 Vue 迷你框架(五)
如何實現 MVVM 類 Vue 迷你框架(五)
上面幾節(jié)課我們已經把數據代理,響應式處理搞完了,接下來需要做什么呢?當然是最難的一部分了,就是我們的編譯模板。
使用到的dom編程方法
element.childNodes - 返回元素子節(jié)點的 NodeList(可直接使用forEach遍歷),換行和空格會被識別成文本節(jié)點。 element.nodeType - 返回元素的節(jié)點類型,元素節(jié)點為 1,文本節(jié)點為 3 element.nodeName - 返回元素的名稱,例如**“DIV”** element.textContent - 設置或返回節(jié)點及其后代的文本內容 element.attributes - 指定節(jié)點的屬性Attr(含有name和value屬性)合 NamedNodeMap(不可直接遍歷)
我們需要做什么呢?
拿到我們需要的 DOM 元素 然后需要解析 {{}}模板插值解析 m-text指令解析 m-html指令
所以我們需要一個編譯模板 Compile 類:
class Compile {
constructor(el, vm) {
this.$el = document.querySelector(el);
this.$vm = vm;
// 判斷是否存在 el
if(this.$el) {
this.compile(this.$el);
}
}
}
判斷節(jié)點是不是具有 {{}} 文本節(jié)點
class Compile {
constructor{
// ...
}
isInter(node) {
return node.nodeType === 3 && /{{.*}}/.test(node.textContent);
}
}
接下來我們封裝一個用于更新指令的公用方法:
update(node, key, dir) {
const fn = this[dir+'Updater']; // 查找指令方法
fn && fn(node, this.$vm[key];
// 更新
new Watcher(this.$vm, key, val => {
fn && fn(node, key)
})
}
如果是文本內容我們就只更新文本:
textUpdater(node, val) {
node.textContent = val
}
text(node, key) {
this.update(node, key, 'text')
}
如果是 html 內容就只更新 htm 內容:
htmlUpdater(node, val) {
node.innerHTML = val
}
html(node, key) {
this.update(node, key, 'html');
}
模板插值解析:
compileText(node) {
this.update(node, RegExp.$1, 'text')
}
最后就是實現 compile(node) 方法:
// 遞歸傳入節(jié)點,根據節(jié)點類型做不同操作
compile(el) {
// 拿到子節(jié)點
const childNodes = el.childNodes;
childNodes.forEach(node => {
if (node.nodeType === 1) {
console.log('元素節(jié)點', node.nodeName);
} else if (this.isInter(node)) {
this.compileText(node);
console.log('文本節(jié)點', node.textContent);
}
if (node.childNodes) {
this.compile(node);
}
});
}
評論
圖片
表情
