1. vue简介
Vue.js是一款MVVM框架,上手快速简单易用,通过响应式在修改数据的时候更新视图。Vue.js的响应式原理依赖于Object.defineProperty
2. vue响应式原理
代码简单实现
将数据变成可观察的
const observable= (that, data) => {
Object.keys(data).forEach(key => {
Object.defineProperty(that, key, {
enumerable: true,
configurable: true,
get (){
return that._data[key];
},
set (newVlaue){
that._data[key] = newVlaue;
that.render(that._data[key]);
}
})
})
}
定义Vue类
lass Vue {
constructor(options) {
this._data = options.data;
this.render = options.render;
this._proxy.call(this, options.data);
}
// 实现data数据代理
_proxy(data) {
const that = this;
observable(that, data);
}
}
写好了来测试下吧
// vue的调用
const app = new Vue({
data: {
number: 0
},
render (value){
console.log(value);
}
})
// 测试响应式
setTimeout(()=>{
app.number = 7;
}, 3000)
代理解释
需要对app._data.text操作才会触发set。为了偷懒,我们需要一种方便的方法通过app.text直接设置就能触发set对视图进行重绘。那么就需要用到代理。代码使用call来实现;
3. vue依赖收集
Dep
用于依赖收集收集的类,在每次get时候进行收集,computed,watch同时也会收集
class Dep{
constructor(){
this.subs = [];
}
add(sub){
this.subs.push(sub);
}
remove(sub){
remove(this.subs, sub);
}
notify(key,value){
const subs = this.subs.slice();
subs.forEach(item=>{
item.update(key,value);
})
}
}
// remove
const remove = (arr, sub)=>{
if(!arr.length) return arr;
const index = arr.indexOf(sub);
if(index>-1){
arr.splice(index, 1);
}
return arr;
}
watcher
在修改data中数据的时候会触发dep对象的notify,通知所有Watcher对象去修改对应视图。
class Watcher{
constructor(vm, callback){
this.callback = callback;
this.vm = vm;
Dep.target = this;
this.callback.call(this.vm);
}
update(key, value){
this.callback.call(this.vm);
}
}
定义vue,依赖收集
const observer = (data, render)=>{
Object.keys(data).forEach(key => {
const dep = new Dep();
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get(value){
if(Dep.target){
dep.add(Dep.target);
}
return value;
},
set(value){
console.log(value, dep);
dep.notify(key,value);
}
})
})
}
class Vue {
constructor(options){
this._data = options.data;
observer(this._data, options.render);
let watcher = new Watcher(this,options.render);
}
}
最后
有什么问题希望指出,欢迎大神指点,vue的其他相关知识会继续更新;