1.0.1 • Published 4 years ago
dvue v1.0.1
vue核心原理演示
数据劫持
模板编译
import Watcher from './watcher.js';
export default class Compiler {
constructor(context) {
this.$el = document.querySelector(context.$el);
this.$data = context.$data;
this.context = context;
// 将dom节点转换成虚拟文档片段
this.$fragment = this.nodeToFragment(this.$el);
// 编译虚拟文档片段
this.compiler(this.$fragment);
// 将虚拟文档片段挂载到dom树上
this.$el.appendChild(this.$fragment);
}
// 将dom节点转换成虚拟文档片段
nodeToFragment(node) {
// 创建一个虚拟文档片段(对其进行操作不会触发dom回流)
let fragment = document.createDocumentFragment();
// 将页面中元素节点添加到虚拟文档片段上
node.childNodes.forEach(child => {
// 元素节点和非空文本节点, 都需要追加到虚拟文档片段中
if(child.nodeType===3&&child.textContent.trim()!==''||child.nodeType===1){
fragment.appendChild(child);
}
});
// 将虚拟文档片返回
return fragment;
}
// 执行模板编译
compiler(node) {
// 通过循环遍历, 执行正则表达式
node.childNodes.forEach(child => {
this.compilerTextNode(child);
});
}
// 编译文本内容
compilerTextNode(node) {
// 匹配插值表达式的正则表达式
const reg = /\{\{(.+?)\}\}/g;
// 执行模板编译
const pieces = node.textContent.split(reg);
const matches = node.textContent.match(reg);
let tokens = [];
pieces.forEach(item => {
if (matches && matches.indexOf(`{{${item}}}`) !== -1) {
tokens.push('(' + item + ')');
} else {
tokens.push('`' + item + '`');
}
});
new Watcher(tokens.join('+'), this.context, value => {
// 更新节点内容
node.textContent = value;
});
}
}
发布者订阅者模式
// 观察者模式中 通知
export default class Dep {
constructor() {
// 存放所有watcher
// this.subs = {0:{update},1:{update}}
this.subs = {}
}
addSub(target) {
this.subs[target.uid] = target
}
notify() {
for (let uid in this.subs) {
this.subs[uid].update()
}
}
}