首先,要实现Vue的Observer和Watcher,需要进行以下步骤:
- Observer:
Vue中的Observer实现了数据响应式,它可以监听数据的变化并自动更新相应的视图。实现Observer需要使用ES6的Proxy对象来劫持对象或数组的访问。代码示例:
function observe(obj) {
if(!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach((key) => {
defineReactive(obj, key, obj[key]);
});
}
function defineReactive(obj, key, val) {
observe(val); // 递归处理
const dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
dep.depend();
return val;
},
set: function reactiveSetter(newVal) {
if(val === newVal) {
return;
}
val = newVal;
observe(newVal);
dep.notify();
}
});
}
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
removeSub(sub) {
remove(this.subs, sub);
}
depend() {
if(window.target) {
this.addSub(window.target);
}
}
notify() {
const subs = this.subs.slice();
for(let i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
}
}
function remove(arr, item) {
if(arr.length) {
const index = arr.indexOf(item);
if(index > -1) {
return arr.splice(index, 1);
}
}
}
在这段代码中,我们使用Object.defineProperty方法重写所需要劫持的对象属性,实现其get和set方法。在get方法中,我们添加了一个依赖收集器Dep,它负责收集Watcher对象,而在set方法中,当其值被更改时,会触发notify方法,通知所有依赖(对应的Watcher对象)更新其视图。
- Watcher:
Watcher作为Observer和Vue之间的桥梁,负责监听数据的变化,并触发响应的更新。它需要接收一个update函数作为参数,在数据变化时调用。代码示例:
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
this.value = this.get();
}
get() {
window.target = this;
const vm = this.vm;
let value = this.getter.call(vm, vm);
window.target = undefined;
return value;
}
update() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
}
}
const bailRE = /[^\w.$]/;
function parsePath(path) {
if(bailRE.test(path)) {
return;
}
const segments = path.split('.');
return function(obj) {
for(let i = 0; i < segments.length; i++) {
if(!obj) {
return;
}
obj = obj[segments[i]];
}
return obj;
}
}
在这段代码中,我们实现了一个Watcher类,它需要接收Vue实例、监听的表达式和回调函数。在get方法中,我们通过parsePath方法解析传入的表达式,获取相应数据,并将当前Watcher对象添加到收集器Dep中。在update方法中,我们触发回调函数,并传递新旧值作为参数。
至此,我们已经成功实现了Vue的Observer和Watcher。
下面是一个简单的示例,演示了如何使用Observer监听对象变化并触发响应的Watcher:
const obj = {a: 1, b: {c: 2}};
observe(obj);
new Watcher(obj, 'b.c', value => {
console.log('b.c changed', value);
});
obj.b.c = 3; // 输出 "b.c changed 3"
再来一个示例,演示如何通过Watcher监听数组元素的变化:
const arr = [1, 2, 3];
observe(arr);
new Watcher(arr, 'length', value => {
console.log('array length changed', value);
});
new Watcher(arr, '1', value => {
console.log('array element changed', value);
});
arr.push(4); // 输出 "array length changed 4"
arr[1] = 5; // 输出 "array element changed 5"
在这个示例中,我们监听了数组的长度变化和第二个元素的变化,当数组长度或第二个元素发生变化时,Watcher对象会触发相应的回调函数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:简单实现Vue的observer和watcher - Python技术站