合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## 自定义指令生效的过程 * 模版编译成 AST 时,解析出指令存在 directives 中 * directives 数据传递到 vnode,vnode.data.dierctives 获取一个节点绑定的指令 * 虚拟 DOM patch 时,触发节点的 create、update、destroy 钩子函数,也会触发节点上属性,事件和指令的更新函数 * 更新指令的程序会监听 create、update、destroy 这几个钩子函数,同时触发指令的钩子函数 * 指令生效 * 视图改变 ![](https://img.kancloud.cn/39/9d/399d63ea7371068cd8273e85fce14c7f_2525x1191.png) ![](https://img.kancloud.cn/d5/0b/d50b6d8b56386db60b745b367df43ba0_1683x413.png) ## 内置指令 *AST 生成代码字符串的过程中,实现内置指令的功能* ### v-if *原理和自定义指令不同* * 模版编译生成代码字符串时,比较特殊 * 根据has变量的值,创建不同的 vnode 节点 ``` // 模版 <li v-if="has">lalala</li> <li v-else> hahaha</li> // 编译后生成的代码字符串 (has) ? _c('li', [_v("lalala")]) : _c('li', [_v("hahaha")]) ``` ### v-for *原理和自定义指令不同* * 模版编译生成代码字符串时,比较特殊 * _l 循环变量list,生成vnode ``` // 模版 <li v-for="( item, index ) in list"> xxx </li> // 编译后生成的代码字符串 _l(( list ), functio ( item, index ) { retuurn _c('li', [_v("xxx")]) }) ``` ### v-on #### 作用于普通元素上,如何监听原生 DOM 事件 事件被保存在vnode中, vnode.data.on 获取一个节点注册的所有的事件 * 事件上的两个钩子函数 create、update,执行 updateDOMListeners * 对比 on 和 oldOn,从而决定是执行绑定还是解绑动作 ``` // 虚拟DOM patch 时,会触发事件的 update 和 ceate var events = { create: updateDOMListeners, update: updateDOMListeners }; function updateDOMListeners (oldVnode, vnode) { // 新旧vnode中没有事件对象,则直接return, 不需要判断应该绑定还是解绑事件 if (!oldVnode.data.on && !vnode.data.on) { return } var on = vnode.data.on || {}; var oldOn = oldVnode.data.on || {}; target = vnode.elm; // 处理特殊情况下的事件,比如 input[type=range] 在IE中的表现 normalizeEvents(on) // 更新事件监听器,判断是 “绑定“ 还是 “解绑“ updateListeners(on, oldOn, add$1, remove$2, createOnceHandler$1, vnode.context); target = undefined; } ``` ##### addEventListener 添加事件监听 ![](https://img.kancloud.cn/6a/99/6a99b537a65eb21b2c331000becf71d2_1144x392.png) 当回调中修改数据,触发 DOM 更新时,那么更新DOM的操作会放在**宏任务**中 #### 作用于自定义元素上,如何监听子组件触发的 自定义 事件