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

vuetransition-group源码分析

时间:2023-03-31 18:16:08 vue.js

在加载或更新transition-group组件DOM时,执行render函数生成标签对应的节点(虚拟节点VNode)。在render函数中,获取transition-group标签中的子标签列表节点(槽),将transition-group标签上的数据依次添加到子标签节点中。同时,通过与更新前的子标签节点进行比较,保存本次更新中仍然存在的子节点和删除的节点。最后返回span标签节点(或自定义标签),将子标签列表作为子节点添加到标签节点中。transition-group动画的实现原理和transition一样。不同的是,transition将标签上的数据添加到一个子标签节点上。transition-group将标签上的数据依次添加到标签列表的每个节点中,可以理解为transition-group相当于在每个子标签外加了一个transition标签。在transition-group组件选项中有一个beforeMount周期函数,在组件加载或更新DOM之前调用。在这个周期函数中,_update函数被重新封装,当render执行完成返回节点时会被调用。首先调用__patch__,将当前存在的label节点作为新节点,移除当前不存在的节点,然后调用originalupdate函数,将当前存在的label节点作为旧节点,添加新节点。封装的_update函数执行了两次__patch__。第一次是从文档中移除当前不存在的旧节点,第二次是在文档中添加一个新节点,完成更新。更新完成后,会调用transition-group组件选项中更新的钩子函数,添加列表的整体过渡效果。label节点添加到文档并更新后,立即通过transform移动到原来的位置,再通过动画移动到当前位置,形成动态效果。varprops=extend({tag:String,moveClass:String},transitionProps);deleteprops.mode;varTransitionGroup={props:props,beforeMount:functionbeforeMount(){varthis$1=this;varupdate=this._update;this._update=function(vnode,hydrating){varrestoreActiveInstance=setActiveInstance(this$1);//强制移除passthis$1.__patch__(//移除当前不存在的旧标签this$1._vnode,//旧标签this$1.kept,//当前保留的旧标签false,//hydratingtrue//removeOnly(!important,避免不必要的移动));this$1._vnode=this$1.kept;恢复活动实例();update.call(this$1,vnode,hydrating);//添加当前添加的标签并调整节点顺序};},render:functionrender(h){vartag=this.tag||这个.$vnode.data.tag||'跨度';varmap=Object.create(null);varprevChildren=this.prevChildren=this.children;//最后一个组件标签中的标签节点(槽)varrawChildren=this.$slots.default||[];//当前组件标签中的标签节点(槽)varchildren=this.children=[];vartransitionData=extractTransitionData(this);//获取标签上的属性for(vari=0;ichildrenmustbekeyed:<"+name+">"));}}}if(prevChildren){varkeeped=[];var删除=[];对于(vari$1=0;i$1