当前位置: 首页 > Web前端 > vue.js

Vue指令源码分析

时间:2023-03-31 15:02:57 vue.js

1.directive,展示两个Vue自带的指令通过extend方法保存在Vue.options.directives上。varplatformDirectives={model:directive,show:show,};extend(Vue.options.directives,platformDirectives);functionextend(to,_from){for(varkeyin_from){to[key]=_from[key]复制代码;}returnto;}2.Vue提供了Vue.directive方法来创建全局指令并将它们添加到Vue.options.directives中。varASSET_TYPES=["component","directive","filter"];ASSET_TYPES.forEach(function(type){Vue[type]=function(id,definition){if(!definition){returnthis.options[type+"s"][id];}else{/*istanbulignoreif*/if(process.env.NODE_ENV!=="production"&&type==="component"){validateComponentName(id);}if(type==="component"&&isPlainObject(definition)){definition.name=definition.name||id;definition=this.options._base.extend(definition);}if(type==="directive"&&typeofdefinition==="function"){definition={bind:definition,update:definition};}this.options[type+"s"][id]=definition;returndefinition;}};});3.notonlyDirectives可以在全局或者组件选项上添加,只在组件内部生效。创建组件时,会格式化组件选项上的指令,并合并全局和组件内指令。/***合并组件选项*/functionmergeOptions(parent,child,vm){...normalizeDirectives(child);//格式化指令...if(!child._base){if(child.extends){parent=mergeOptions(parent,child.extends,vm);}if(child.mixins){for(vari=0,l=child.mixins.length;i

指令分析结果:{directives:[{name:"test",rawName:"v-test:name.fale",value:getName,expression:"getName",//表达式arg:"name",//参数修饰符:{fale:true},//修饰符},];}5.节点在渲染过程中(创建DOM或组件,更新节点,插入父DOM元素,销毁节点),会调用很多钩子处理节点对应标签的各种数据。这些钩子包括命令的create、update、destroy三个钩子函数,在节点渲染过程中会被调用。这里的钩子函数与指令定义时的钩子函数不同。/*指令钩子函数*/varemptyNode=newVNode("",{},[]);vardirectives={create:updateDirectives,//创建DOM元素后调用update:updateDirectives,//更新节点时调用destroy:functionunbindDirectives(vnode){//调用updateDirectives(vnode,emptyNode);},};functionupdateDirectives(oldVnode,vnode){if(oldVnode.data.directives||vnode.data.directives){_update(oldVnode,vnode);}}6.命令的三个钩子将调用_update函数。function_update(oldVnode,vnode){varisCreate=oldVnode===emptyNode;varisDestroy=vnode===emptyNode;varoldDirs=normalizeDirectives$1(oldVnode.data.directives,oldVnode.context);//旧标签节点上的指令数据收集(包括标签上的指令信息和指令定义)varnewDirs=normalizeDirectives$1(vnode.data.directives,vnode.context);//新标签节点上的指令数据收集(包括指令信息和标签定义上的指令)vardirsWithInsert=[];vardirsWithPostpatch=[];varkey,oldDir,dir;for(keyinnewDirs){oldDir=oldDirs[key];dir=newDirs[键];if(!oldDir){//指令第一次绑定到元素//newdirective,bindcallHook$1(dir,"bind",vnode,oldVnode);//调用绑定钩子函数if(dir.def&&dir.def.inserted){dirsWithInsert.推(目录);}}else{//现有指令,更新dir.oldValue=oldDir.value;//更新指令的值dir.oldArg=oldDir.arg;//更新指令的参数(指令参数可以动态改变)callHook$1(dir,"update",vnode,oldVnode);如果(dir.def&&dir.def.componentUpdated){dirsWithPostpatch.push(dir);}}}if(dirsWithInsert.length){varcallInsert=function(){for(vari=0;i