编译阶段之parse
template
ast
- parse阶段
- 在generate阶段有对el属性进行添加值的
流程
总结
1.在闭合标签后执行closeElement,然后执行processElement执行processAttrs。
2.processAttrs获取到el.attrsList,遍历判断name是否是指令,是的话获取修饰符通过对象返回出来。
3.判断name不为Bind不为on进入else逻辑,首先去掉v-标签,然后调用addDirective向el中添加directives属性。
4.如果name不是指令,调用addAttr向el中添加attrs属性。
编译阶段之generate
流程
总结
patch
流程
总结
1.首先patch开始时会创建cbs对象和hooks,遍历Hooks为cbs添加hook属性为数组,接着继续遍历modules把modules定义相同hooks丢进数组中。最终返回cbs对象。
2.对于create除了按顺序执行存在data属性会调用invokeCreateHooks之外,在创建组件初始化完成时调用initComponent也会调用invokeCreateHooks。
3.invokeCreateHooks就是遍历调用cbs.create的函数,也就是执行updateDirectives,updateDOMListeners等钩子函数,传入空vnode和vnode,
4.updateDOMListeners获取到vnode.data.on对象和获取vnode.elm节点,执行updateListeners,遍历on对象,cur=createFnInvoker返回的函数,把回调赋值给了invoker.fns,此函数是执行回调用的,然后调用add也就是调用addEventListener给节点添加事件和此函数,案例中这里我们就为节点添加上了Input事件函数。
5.接着是updateDirectives,这里我们主要是对el.directives添加了def属性,属性值是平台定义的directives,返回值是inserted和componentUpdated函数。接着会判断是否是第一次渲染也就是不存在oldVnode,然后就会调用inserted钩子函数。
6.inserted钩子函数有对select和其他类型的操作,这里对于Input,为节点添加了compositionstart,compositionend和change事件。对于compositionstart把e.target.composing设为true,对于compositionend把e.target.composing设为false,然后手动触发节点已绑定的input事件。input事件回调是这样的if(event.target.value。所以对于中文输入判断是否是预输入而确定是否需要实时更新。此外对于change事件注释说是为了兼容Safari<10.2 等那些不会触发 compositionend 的浏览器。也就是备胎!!!
总结
v-model实际上就是通过修改 AST 元素,给 el 添加⼀个 prop ,相当于我们在 input 上动态绑定了 value ,⼜给 el 添加了事件处理,相当于在 input 上绑定了 input 事件。其实就是动态绑定了 input 的 value 指向了 msg 变量,并且在触发 input 事件的时候去 动态把 msg 设置为⽬标值,这样实际上就完成了数据双向绑定了。而对于预输入又做了一层的优化。