transition组件解析
Function
工具函数
- getRealChild
- extractTransitionData
- isSameChild
流程
总结
1.transition组件和keep-alive组件⼀样,都是内置组件,⽽transition的定 义在 src/platforms/web/runtime/component/transtion.js 中,之所以在这⾥定义,是因为transition组件是 web 平台独有的。transition组件也是个抽象组件只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。
2.对于transition的props属性定义了一堆。
3.对于transition的render
- 获取组件内部内容,无内容直接返回。
- 过滤空白及文本节点,过滤后无内容直接返回。
- 包裹多个并列子节点 报错。
- 对mode值的判断 报错。
- 获取到子节点。
- 如果父节点也有transition 那么跳过此transition 没有意义。
- 获取真实节点 如果包裹的是keep-alive的话就会递归遍历找到真实的节点 如果不存在真实节点直接返回。
- 构造id 构造子节点的key。
- 给子节点data添加transition属性 属性内容是通过transition的属性和事件提取数据赋值。
- 最后就是旧节点的相关处理,这里需要注意的是前置条件isSameChild即不是相同子节点,isSameChild的判断是新旧key值相同并且是相同类型tag。当有相同标签名的元素切换时,需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 组件中的多个元素设置 key 是一个更好的实践,所以对于相同标签名切换只会替换内容,而不会应用过渡效果。
transition过渡效果处理逻辑
Vue在插入、更新或移除DOM时,提供多种不同方式的应用过渡效果,实际上具体分为2类:
- 使用css来应用过渡效果。
- 使用钩子函数来应用过渡效果。
template
工具函数
- resolveTransition
- getHookArgumentsLength
- nextFrame
- whenTransitionEnds
流程
总结
1.首先patch开始时会创建cbs对象和hooks,遍历Hooks为cbs添加hook属性为数组,接着继续遍历modules把modules定义相同hooks丢进数组中。最终返回cbs对象。
2.对于create除了按顺序执行存在data属性会调用invokeCreateHooks之外,在创建组件初始化完成时调用initComponent也会调用invokeCreateHooks。
3.invokeCreateHooks就是遍历调用cbs.create的函数,也就是执行_enter,传入空vnode和vnode。
4.对于enter
- 主要就是获取组件data的transition属性然后进行解析,返回对象赋值给data。
- 通过data解析出变量。
- 判断是否存在appear属性不存在直接返回首次不会执行动画过渡。
- 获取过渡类名,获取钩子函数,指定过渡时间。
- 判断expectsCSS(是否使用css来应用过渡效果)和userWantsControl(是否用户控制结束事件,判断enter钩子函数的参数个数) 。
5.使用css来应用过渡效果:
- 添加startClass即v-enter。
- 添加activeClass即v-enter-active。
- 使用requestAnimationFrame或setTimeOut,浏览器在下次渲染后调用指定的回调函数执行相关逻辑:移除startClass即v-enter,添加toClass即v-enter-to。
- 是否延时处理,延时处理调用setTimeout处理,否则调用whenTransitionEnds,侦听过渡结束后调用回调,回调首先移除toClass即v-enter-to,接着移除activeClass即v-enter-active。
6.使用钩子函数来应用过渡效果:
- 首先执行beforeEnterHook钩子函数。
- 接着执行enterHook钩子函数传入cb,当用户调用done()是执行回调。
- 如果cb.cancelled取消了,执行enterCancelledHook钩子函数否则执行afterEnterHook钩子函数。
7.对于leave
- 主要就是获取组件data的transition属性然后进行解析,返回对象赋值给data。
- 通过data解析出变量。
- 判断是否存在appear属性不存在直接返回首次不会执行动画过渡。
- 获取过渡类名,获取钩子函数,指定过渡时间,判断是否延迟离开。
- 判断expectsCSS(是否使用css来应用过渡效果)和userWantsControl(是否用户控制结束事件,判断leave钩子函数的参数个数) 。
8.使用css来应用过渡效果:
- 添加leaveClass即v-leave。
- 添加leaveActiveClass即v-leave-active。
- 使用requestAnimationFrame或setTimeOut,浏览器在下次渲染后调用指定的回调函数执行相关逻辑:移除leaveClass即v-leave,添加leaveToClass即v-leave-to。
- 是否延时处理,延时处理调用setTimeout处理,否则调用whenTransitionEnds,侦听过渡结束后调用回调,回调首先移除leaveToClass即v-leave-to,接着移除leaveActiveClass即v-leave-active。
9.使用钩子函数来应用过渡效果:
- 首先执行beforeLeave钩子函数。
- 接着执行leave钩子函数传入cb,当用户调用done()是执行回调。
- 如果cb.cancelled取消了,执行leaveCancelled 钩子函数否则执行afterLeave钩子函数。
10.在 leave 动画执⾏完后,它会执⾏ rm 函数把节点从 DOM 中 真正做移除。
总结
⾃动嗅探⽬标元素是否应⽤了CSS过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
如果过渡组件提供了JavaScript钩⼦函数,这些钩⼦函数将在恰当的时机被调⽤。
如果没有找到JavaScript钩⼦并且也没有检测到CSS过渡/动画,DOM操作(插⼊/删除)在下⼀帧中⽴即执⾏。
所以真正执⾏动画的是我们写的CSS或者是JavaScript钩⼦函数,⽽transition只是帮我们很好地管理了这些 CSS 的添加/删除,以及钩⼦函数的执⾏时机。