JSFiddle - React, Tailwind, and code Playground
by ruirui
HTML
vue 动态数据绑定(五)
<div id="app">
<p>姓名:<span>{{user.name}}</span></p>
<p>年龄:<span>{{user.age}}</span></p>
</div>
<input type="text" id="input">
JavaScript
function Vue(obj) {
this.el = obj.el;
this.data = obj.data;
new Observer(this.data);
new Compile(this.el, this);
}
/*-----------------------Observer--------------------*/
function Observer(data) {
this.data = data;
if(Array.isArray(data)){
// 暂不考虑数组
}else{
this.makeObserver(data);
}
}
Observer.prototype.makeObserver = function(data) {
var self = this;
for (var i in data) {
if (data.hasOwnProperty(i)) {
if (typeof data[i] === 'object') {
new Observer(data[i]);
} else {
this.getset(i, data[i]);
}
}
}
}
Observer.prototype.getset = function (i, value) {
let val = value;
let self = this;
var dep = new Dep();
Object.defineProperty(this.data, i, {
configurable: true,
enumerable: true,
get: function () {
console.log('你访问了' + i);
if(Dep.target){ // 注意:这里进行收集依赖
dep.addSub(Dep.target);
}
return val;
},
set: function (newval) {
console.log('你设置了' + i + ',新的值为' + newval);
if(val === newval) {
return
}
val = newval;
if(typeof newval === 'object') {
new Observer(val);
}
dep.notify();
}
})
}
/*-----------------------Dep--------------------*/
function Dep () {
this.subs = []; // 观察者合集
}
Dep.target = null; // 全局唯一的 Watcher,看是谁在进行依赖收集
// 向subs数组添加依赖
Dep.prototype.addSub = function (sub) {
this.subs.push(sub);
};
Dep.prototype.notify = function () {
// 通知所有订阅者更新
this.subs.forEach((item) => {
item.update();
})
};
/*-----------------------Watcher--------------------*/
function Watcher(vm, exp, cb) {
Dep.target = this; // Watcher 初始化的时候,将Dep.target指向全局唯一的 Watcher
this.vm = vm;
this.cb = cb;
this.exp = exp;
this.get();
Dep.target = null;
}
Watcher.prototype.get = function() {
return CompileUtil.parse(this.exp)(this.vm.data); // 获取值得时候会触发属性的getter添加监听,这样就将观察者加入了订阅器中,然后清空Dep.target。
}
Watcher.prototype.update = function() {
// 获得新值
this.newVal =...