1.何为响应式?
当一个数据发生改变,视图会随之刷新,并匹配最新的值。就叫响应式。
2.如何实现响应式?
初步构想,一个数据的改变应该会有监听函数,去监听其数据改变,并有办法去通知其视图的更改
3.实现监听--首先请出Object.defineProperty函数,先看个demo
var obj = {
name: '11',
sex: '男'
}
let keys = Object.keys(obj)
for(let i in keys){
let value = obj[keys[i]]
Object.defineProperty(obj, keys[i], {
get(){
console.log('get')
return value
},
set(){
console.log('set')
}
})
}
console.log(obj.name) //打印出get 11
obj.name = '张三' //打印出set
从这个示例中可以看出通过Object.defineProperty函数我们可以实现对object的get和set函数的重写。那么下一步我们需要对其进行监听。
4.实现依赖当前数据的收集
1.首先我们先实现一个简单的对依赖收集的类
class Dep {
constructor(){
this.subs = []
},
//增加
depend(){
if(window.target){
this.subs.push(window.target) //这个window.target(也就是后面的watcher)我们暂时不急着解释
}
},
//通知
notify(){
const subs = this.subs.slice()
for(let i = 0, l=sub.length; i < l; i++){
subs[i].notify()
}
}
//还有一些增删的方法自行去看源码
}
2. 开始进行依赖的收集
function defineReactive(data, key, val){
let dep = new Dep()
Object.defineProperty(data, key, {
get: function(){
dep.depend()
return val
},
set: function(newVal){
if(val === newVal) return
val = newVal
dep.notify();
})
}
3.因为上面我们说的是一个属性的监听,而我们希望监听到对象的所有属性,所以我们再封装一个Observer类去作为中间层接受对象(也就是vm.$options.data)处理
export class Observer{
constructor(value){
this.value = value;
if(!Array.isArray(value)){
this.walk(value)
}
}
walk(obj){
const keys = Object.keys(obj)
for(let i = 0; i <= keys.length; i++){
defineReactive(obj, keys[i], obj[keys[i]])
}
}
}
5.总结(我们大致的流程图)
6.夺命三问
1.所以我们为什么监听不到对象属性的新增?
因为对象增加属性(比如this.obj.age = 22),并没有对其age属性进行get,set的监听和收集,所以自然不会触发视图更新
2.已知我们vue.$options.data是对象。那里面的数组是如何触发更新的?
等下一篇文章详解
3.第三问捏造不出来了