目录
watch
用法,vm.$watch(a.b.c, function(){}, { deep:true/ immediate: true })
deep: true 监听内部值的变化,数组不用
immediate: true 使用时,立即以当前值触发回调函数
vm.$watcher内部实现
1,new Watcher实现chapter2中的watcher
2, 判断是否含有immediate的option,如果有,则立即使用当前值执行回调函数
3, return unwatchFn 实现取消监听,内部为watcher.teardown()
Watcher 关于chapter2新增内容.
1,支持function为expOrfn。
如果是function则将getter设置为function
否则设置为参数的路径parsePath()
这样做把getter设置为function或者路径
可以在后续调用的时候使用this.get(),把原先在window.target = this这里设置的唯一位置保存到参数的dep里。
(回顾一下,object在defineproperty里存和notify, array在defineproperty里存,在observer里notify,因为array需要在observer里重写方法)
2,watcher中也有deps和depIds,用来记录当前watcher在哪些dep上有储存。depids存新增哪些dep的id号,deps存this
如果watcher的参数是函数,则可能有多个dep,要记录函数使用参数的dep
teardown => 循环调用deps[i]的removesub。
dep里removesub => indexof + splice()
####deep实现原理
window.target = undefined 之前运行函数traverse()触发内部元素的收集dep,收集对象为当前父的this
val[key[i]]会触发getter
vm.$set
用法 vm.$set(target,key,value)
array ⇒ splice()
object => target 含_ob_ 则defineproperty, 不含直接加,意味着本身父级就不是响应式的
vm.$delete
用法vm.$delete(target, key)
array => splice()
obj => 依旧判断是否存在,是否为响应式,然后delete+notify
虚拟dom
状态作为输入生成DOM=>显示称之为渲染,program运行会产生状态改变=>新的dom。频繁的操作dom代价太大。虚拟dom是一种解决方法,(React,vue), 通过保存上一次的状态进行对比来减少操作dom的数量。
vue1.0太细,每个节点都有watcher。
Vue2.0以组件为单位创建watcher,知道组件变化之后,再通过对比找到改变的节点。
模板=>渲染函数=>vnode=>(patch)=>视图
VNode
javascript 的对象=> 注释节点,文本节点,元素节点,组件节点,函数式节点,克隆节点
真实的dom元素信息都在vnode里,通过vnode来创建真正的dom元素
创建节点的过程:
只有三种节点会被插入到dom中,元素节点,注释节点,文本节点
1,判断tag属性 => 存在tag,意味着是元素节点 => document.creatElement => 遍历children ,创建children => appendchild
2,不存在tag => createTextNode / createComment
删除节点
1,nodeOps => removeChild 的跨平台封装
更新节点
情况:
静态节点直接跳过
是否有文本属性,有则直接替代
元素节点
=> 有children 稍后讨论
=> 无children 删的只剩空
有children,更新子节点
1,创建字节点,new做参考循环old,old不存在,创建新,插入未处理的前面(不是已处理的后面,已处理的后面会导致顺序相反,因为是对原dom进行操作,已处理后面会导致后续的未处理节点使用同一个已处理节点后面的位置,已处理没有更新,比较是虚拟dom的比较,插入是真实dom的插入)
2,更新子节点,同上更新节点
3,移动字节点,移到所有未处理的前面,Node.insertBefore()
4,删除子节点,new节点循环后,old剩余的删掉
优化策略
新前 new未处理的第一个
新后 new未处理的最后一个节点
旧前 old未处理第一个节点
旧后 old未处理最后一个节点
新前旧前,对比是否为同一个
新后旧后,对比是否为同一个
新后旧前,对比,移位
新前旧后,对比,移位
判断未处理的节点
准备四个节点记录只记录未处理的节点,跟上面优化一样,新前新后,旧前旧后
patch
patching 算法来增删改现有的dom,用javascript的计算成本来换dom的操作成本
模板编译
如何让虚拟DOM拿到vnode
模板 => 模板编译 => 渲染函数 => vnode => 用户界面
模板=>渲染函数
模板 => AST(Abstract Syntax Tree) 抽象语法树 => 渲染函数
逻辑总结大概是三个部分
模板解析成AST (解析器)=> 遍历AST标记静态节点(优化器) => AST生成渲染函数(代码生成器)
解析器可分为 html解析器 文本解析器 过滤器解析器 具体下周再看