美文网首页
Vue transition探索

Vue transition探索

作者: merrylmr | 来源:发表于2020-02-09 22:18 被阅读0次

    使用过Vue的小伙伴都知道,Vue的内置组件transition,在以下情况,可以给单个元素/组件添加进入/离开的过渡

    • 条件渲染(v-if)
    • 条件展示(v-show)
    • 动态组件
    • 组件根节点

    这篇文章主要解密:条件展示(v-show)下,html+css+js实现一个简单的transition

    先来看看vue官网文档:进入/离开&列表过渡

    Vue的过渡实现步骤

    1.自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名
    2.如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用
    3.如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行

    所以真正执行动画的是我们写的css或者javascript钩子函数,而Vue的transtion只是帮我们很好地管理了这些css的添加/删除,以及钩子函数的执行时机。

    过渡的类名

    name 定义 添加时间 移除时间
    v-enter 过渡的开始状态 元素被插入之前 元素被插入的下一帧移除
    v-enter-active 过渡生效时候的状态 被插入之前 过渡/动画完成
    v-enter-to 过渡结束状态 元素被插入之后下一帧 过渡/动画完成
    v-leave 离开过渡的开始状态 离开过渡触发时刻 下一帧
    v-leave-active 离开过渡生效的状态 离开过渡触发 过渡/动画完成
    v-leave-to 离开过渡结束状态 离开过渡触发下一帧 过渡/动画完成

    过渡/动画完成后移除class:怎么判断过渡/动画是否完成?可以监听对应的事件:

    • 过渡完成:transitionend
    • 动画完成:animationend

    了解了以上知识点,实现一个简单的transition就非常的简单了。
    查看demo效果:https://merrylmr.github.io/vue-theory-analysis/

    效果图

    核心源码

      class Transition {
        constructor(el, name, show) {
          this.el = el
          this.show = show || false // el初始状态,显示or隐藏
          this.x = this.autoCssTransition(name)
    
          this.enterCb = function () {
            el.style.display = 'block'
          }
          this.leaveCb = function () {
            el.style.display = 'none'
          }
          this.init(el)
        }
    
        autoCssTransition(name) {
          return {
            enterClass: `${name}-enter`, // start-class
            enterToClass: `${name}-enter-to`, // toClass
            enterActiveClass: `${name}-enter-active`, //动画完成删除
            leaveClass: `${name}-leave`,
            leaveToClass: `${name}-leave-to`,
            leaveActiveClass: `${name}-leave-active`
          }
        }
    
        addTransitionClass(el, cls) {
          el.classList.add(cls)
        }
    
        removeTransitionClass(el, cls) {
          el.classList.remove(cls)
        }
    
        init(el) {
          if (!this.show) {
            el.style.display = 'none'
          }
    
          let {
            enterToClass,
            enterActiveClass,
            leaveToClass,
            leaveActiveClass
          } = this.x
    
          let cb = () => {
            if (this.show) {
              this.removeTransitionClass(el, enterToClass)
              this.removeTransitionClass(el, enterActiveClass)
    
            } else {
              this.removeTransitionClass(el, leaveToClass)
              this.removeTransitionClass(el, leaveActiveClass)
              this.leaveCb()
            }
          }
    //     监听CSS过渡执行完成
          el.addEventListener('transitionend', cb)
    //      监听css动画动画执行完成
          el.addEventListener('animationend', cb)
        }
    
        enter() {
          this.show = true
          this.enterCb()
          this.addTransitionClass(this.el, this.x.enterClass)
          this.addTransitionClass(this.el, this.x.enterActiveClass)
          // 下一帧
          nextFrame(() => {
            this.removeTransitionClass(this.el, this.x.enterClass)
            this.addTransitionClass(this.el, this.x.enterToClass)
          })
        }
    
        leave() {
          this.show = false
          this.addTransitionClass(this.el, this.x.leaveClass)
          this.addTransitionClass(this.el, this.x.leaveActiveClass)
       // 下一帧
          nextFrame(() => {
            this.removeTransitionClass(this.el, this.x.leaveClass)
            this.addTransitionClass(this.el, this.x.leaveToClass)
          })
        }
    
        toggle() {
          if (!this.show) {
            this.enter()
          } else {
            this.leave()
          }
        }
      }
    

    简单使用

    // css
     .slide-top-enter,
        .slide-top-leave-to {
          transform: translateY(-100%);
        }
    
        .slide-top-enter-active,
        .slide-top-leave-active {
          transition: all 0.3s ease;
        }
    // js:
     let instance = new Transition(box, 'slide-top')
      btn.addEventListener('click', () => {
        instance.toggle()
      })
    

    相关文章

      网友评论

          本文标题:Vue transition探索

          本文链接:https://www.haomeiwen.com/subject/geqvactx.html