Vue源码之transition

776 阅读5分钟

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 中 真正做移除。

总结

  1. ⾃动嗅探⽬标元素是否应⽤了CSS过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。

  2. 如果过渡组件提供了JavaScript钩⼦函数,这些钩⼦函数将在恰当的时机被调⽤。

  3. 如果没有找到JavaScript钩⼦并且也没有检测到CSS过渡/动画,DOM操作(插⼊/删除)在下⼀帧中⽴即执⾏。

  4. 所以真正执⾏动画的是我们写的CSS或者是JavaScript钩⼦函数,⽽transition只是帮我们很好地管理了这些 CSS 的添加/删除,以及钩⼦函数的执⾏时机。