vue2.0版本,数据响应式原理,个人总结笔记
//视图更新
function updateView(){
console.log("视图更新了")
},
//重新定义数组原型
const oldArrayProperty = Array.prototype
//创建新对象,原型指向 oldArrayProperty,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty)
['push','pop','shift','unshift','splice'].forEach(mothdName=>{
arrProto[mothdName] = function(){
updateView()//触发视图更新
oldArrayProperty[methodName].call(this,...arguments)
}
})
//重新定义属性,监听起来
function defineReactiv(targer,key,value){
//深度监听
let chilidDep = Observer(value)
//给data里面的每一个属性添加一个dep
let dep = new Dep()
//核心 API
//将dep存起来,当页面取值时,说明这个值用来渲染,在将这个watcher和这个属性对应起来
Object.defineProperty(targer,key,{
get(){//依赖收集
if(Dep.targer){//让这个属性记住这个watcher
dep.depend()
}
//当我们对arr取值的时候,我们就让数组的dep记住这个watcher
if(chilidDep){
chilidDep.dep.depeng()//数组收集watcher
}
//检测一下dep
//获取arr的值,会调用get方法 希望让当前数组记住这个渲染watcher
//console.log(dep.subs)
return value
},
set(newValue){//依赖更新
//注意设置的值和原来的值是一样的
if(newValue !== value){
//设置新值的时候也要深度监听
observer(newValue)
//设置新值
//注意,value一直在闭包中,此处设置完之后,再get时也是会获取最新的值
value = newValue
//触发更新视图 watcher会通知视图更新,dep.notify()
updateView()
}
}
})
}
//监听对象属性
function observer(target){
if(typeof target !== 'object' || target === null){
//不是对象或者数组
return target
}
if(Array.isArray(target)){
target.__proto__ = arrProto
}
//重新定义各个属性(for in 也可以遍历数组)
for(let key in target){
defineReactiv(target,key,target[key])
}
}
//准备数据
const data = {
name:'zhangsan',
age:20,
info:{
address:'北京' //需要深度监听
},
nums:[10,20.30]
}
//监听数据
observer(data)
//测试
data.name = 'list'
data.age = 21
data.x = '100' //新增属性,监听不到 --所以有Vue.set
delete data.name //删除属性,监听不到 --所以有Vue.delete
data.info.address = '上海' //深度监听
data.nums.push(4) //监听数组
Vue中如何进行依赖收集呢?
每个属性都有一个dep,存放这我们所有依赖的watcher,当属性变化后,通知自己的对应的watcher去更新,默认在渲染的时候(获取这个响应式数据),此时就会触发属性收集依赖dep.depend(),当属性发生改变是,触发watcher,通过dep.notify()更新视图。
每一个data里面的属性都有一个dep。dep是一个数组,存放watcher,只要在页面上使用这个属性,就有一个watcher