vue(实例化静态变量,成员变量)
1、存储vue的options
2、存储vue的el
3、存储vue options的data,存放到$data
4、把$data里面的数据挂载到vue实例上,
Object.keys(this.$data).forEach(key=>{
Object.defineProperty(this,key,{
//可枚举
//可配置
//setter
//getter
})
})
//这里不用递归赋值
5、调用observe对象,生成getter,setter函数
6、调用compile对象,生成相应的模板
Observe(对于vue中的对象生成响应式对象)
1、构造函数,接受data
constructor(data){
this.walk(data))
}
2、walk 循环data中的属性
if(!data || type data!=='object'){
return
}
object.keys(data).forEach(key=>{
this.defineReactive(data,key,data[key])
})
3、defineReactive 针对于每个属性生成相应的getter,setter方法
defineReactive(data,key,val){
//这里传入val避免调用get方法时发生死循环
let dep=new Dep()
//递归调用,生成getter,setter
this.walk(val)
object.defineProperty(data,key,{
...
set(newVal){
if(newVal!==val){
data[key]=newVal
//如果重新赋值为对象也需要生成getter,setter 响应式
this.walk(newVal)
dep.notify()//发布通知
}
},
get(){
//收集依赖,添加watcher
Dep.target&&Dep.addSubs(Dep.target)
return val
}
})
}
compile(模板数据解析为dom数据)
1、接受vue实例
2、存储vue的el
3、遍历el中的vnode 解析相关的内容
4、判断是否为文本标签/元素节点(isTextNode,isElementNode)
5、元素节点需要判断是否由指令(v-*) (isDrective)
6、为文本标签,解析内容是否为差值表达式
let reg = /{{(.+?)}}/
let value=node.textContent
if(reg.test(value)){
let key=RegExp.$1.trim()
node.textContent=value.replace(reg,this.vm[key])
}
7、元素节点解析相应的指令
Array.from(node.attributes).forEach(attr=>{
let attrName=attr.name
if(this.isDrective(attrName)){
attrName=attrName.substr(2)
let key=attr.value
this.update(node,key,attrName)
}
})
update(node,key,attrName){
let updateFn=this[attrName+"Update"]
updateFn&&updateFn.call(this,node,this.vm[key],key)
}
textUpdater(node,value,key){
8、当解析v-model时为当前input控件添加input事件,触发了set方法->触发了Dep的notify 方法
node.addEventListener('input',()=>{
this.vm[key]=node.value
}))
Dep(依赖收集,发布通知,观察者模式)
1、初始化subs=[],存放相关的依赖
2,addSub方法,添加依赖
3、notify 调用subs里面的watcher里的update方法
watcher(观察者)
1、参数为vue实例,data中属性名称,回调函数
constructor(vm,key,cb)
2、调用Dep
设置Dep.target=this //当前watcher
获取this.vm[key] 设置为旧值
设置Dep.target=null 防止重复添加
调用this.vm[key] 会调用相应属性的get方法
此时Dep.target有值,会调取Observe里面的属性get方法,Dep.target&&Dep.addSub(Dep.target)
添加依赖
当vue data 里面的值发生变化时,会调取Observe里面属性定义的set方法,调取dep.notify()
通知相应的watcher 调用update方法
\