class Dep { // 存储订阅者
constructor() {
this.dep = [];
}
add(data) {
this.dep.push(data)
}
notice() {
this.dep.forEach(v => {
v.updata()
})
}
}
class Observer { // 数据代理
constructor(data) {
this.analysisData(data);
this.dep = new Dep();
}
analysisData(data) {
if (Object.prototype.toString.call(data) === '[object Object]') {
Object.keys(data).forEach(key => {
let value = data[key];
this.analysisData(value);
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: () => {
if (Dep.target) {
this.dep.add(Dep.target); // 存储订阅者
}
return value
},
set: (newValue) => {
value = newValue;
this.dep.notice(); // 通知所有订阅者数据更新
return value;
}
})
})
}
}
}
class Watcher {
constructor(data, key, callback) {
this.data = data;
this.key = key;
this.value = this.get();
this.callback = callback;
}
get() {
Dep.target = this;
const value = this.data[this.key];
Dep.target = null;
return value;
}
updata() { // 数据更新,更新视图
if (this.value !== this.data[this.key]) {
this.value = this.data[this.key];
this.callback();
}
}
}
class Compile { // 数据和dom绑定
constructor(data, id) {
this.root = document.querySelector(id);
this.reg = /\{\{(.*)\}\}/;
this.data = data;
this.compile(this.root, this.reg);
}
compile(root, reg) {
let childNodes = root.childNodes;
[...childNodes].forEach((node) => {
let text = node.textContent;
if (node.nodeType === 3 && reg.test(text)) {
let key = reg.exec(text)[1];
this.addWatcher(key, node);
node.textContent = this.data[key];
}
if (node.childNodes && node.childNodes.length > 0) {
this.compile(node, reg)
}
})
}
addWatcher(key, node) {
new Watcher(this.data, key, () => {
node.textContent = this.data[key]
})
}
}
class MyVue {
constructor({
el,
data
}) {
new Observer(data);
new Compile(data, el)
}
}
const data = {
name: '小明'
};
new MyVue({
el: '#root',
data
})
setTimeout(() => {
data.name = '小红'
}, 3000)
实现数据改变,视图同步功能
最新推荐文章于 2022-11-02 15:54:27 发布