新手上路还望各位大佬指教
简单实现下vue的双向绑定和nextTick
html片段
<body>
<div id="title"></div>
</body>
js代码片段
// 对象
let obj = {
name: 'will'
}
// Dep函数
function Dep() {
this.subs = []
}
Dep.prototype.addSub = function (sub) {
this.subs.push(sub)
}
Dep.prototype.addSub = function (sub) {
this.subs.push(sub);
};
Dep.prototype.depend = function () {
if (Dep.target) {
Dep.target.addDep(this);
}
};
// 通知更新
Dep.prototype.notify = function notify() {
// stabilize the subscriber list first
var subs = this.subs.slice();
for (var i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
};
Dep.target = null;
// 装载dep.target
function pushTarget(target) {
Dep.target = target;
}
// 卸载dep.target
function popTarget(target) {
Dep.target = target;
}
var uuid = 0
// watcher函数
function Watcher(expOrFn, opction) {
this.id = ++uuid
this.getter = expOrFn
this.get()
this.befor = opction.befor// 生命周期
}
Watcher.prototype.get = function () {
//Dep.target = this
pushTarget(this)
this.getter()
popTarget()
}
Watcher.prototype.addDep = function (dep) {
//var id = dep.id;
dep.addSub(this);
};
Watcher.prototype.update = function () {
// 开启dom跟新队列
queueWatcher(this)
};
Watcher.prototype.run = function () {
this.befor() // 执行生命周期
this.get()
};
var pedding = false; //等待开启队列
// 异步任务
var timerFunc = function () {
Promise.resolve().then(flushCallbacks);
};
// 调用队列
function flushCallbacks() {
var copies = callbacks.slice(0);
callbacks.length = 0;
for (var i = 0; i < copies.length; i++) {
copies[i]();
}
}
// 执行队列
var callbacks = [];
// 将任务放入队列住的函数
function nextTick(cb) {
callbacks.push(function () {
if (cb) {
cb.call()
}
})
if (!pedding) { // 等待队列中的函数执行完再次加入队列
pedding = true;
timerFunc();
}
}
// 执行更新dom
var queue = []
function flushSchedulerQueue() {
for (index = 0; index < queue.length; index++) {
queue[index].run()
}
}
// 将watcher加入队列
var has = {}
function queueWatcher(watcher) {
console.log(watcher)
var id = watcher.id
// 避免dom重复更新 只会加入一个watcher
if (has[id] == null) {
has[id] = true;
queue.push(watcher)
// 将更新dom事件加入 队列进行顺序调用
nextTick(flushSchedulerQueue)
}
}
// 双向绑定函数
function Observer(data) {
if (data.constructor == Object) {
this.walk(data)
}
}
Observer.prototype.walk = function (obj) {
for (var key in obj) {
defineReactive$$1(obj, key)
}
}
// 双向绑定
function defineReactive$$1(data, key) {
var b = data[key];
var dep = new Dep()
Object.defineProperty(obj, 'name', {
get: function (value) {
console.log('获取')
console.log(dep)
if (Dep.target) {
dep.depend()
}
return b
},
set: function (value) {
dep.notify()
b = value
}
})
}
// 模拟调用
new Observer(obj)
function updateComponent() {
title.innerText = obj.name
}
new Watcher(updateComponent, {
befor: function () {
// 调用beforeUpdate生命周期
console.log('beforeUpdate')
}
})
// 绑定事件
title.onclick = function () {
//obj.name = 2
for (let i= 0; i < 10; i++ ) {
obj.name = i
}
nextTick(() => {
console.log(title)
})
console.log(obj.name)
}