<!--注意：外部容器只能用v-show来条件渲染-->

<template>
    <transition :name="$style.slide"
                @before-enter="beforeEnter" @after-enter="afterEnter"
                @before-leave="beforeLeave" @after-leave="afterLeave">
        <slot></slot>
    </transition>
</template>

<style module>
    .slide:global(-enter-active),
    .slide:global(-leave-active) {
        overflow: hidden;
    }

    .slide:global(-enter),
    .slide:global(-leave-to) {
        height: 0 !important;
    }
</style>

<script>
    import {prefixed} from '../../tools/prefix/index'

    let durationName = prefixed('transitionDuration')
    let timingFunctionName = prefixed('transitionTimingFunction')

    export default {
      props: {
        duration: {
          type: Number,
          default: 300
        },
        timingFunction: {
          type: String,
          default: 'ease'
        }
      },
      computed: {
        $style () {
          return this.$options.cssModules
        }
      },
      methods: {
        /**
             * vue过渡enter顺序
             * 执行beforeEnter钩子->添加enter,enter-active类并显示元素->执行enter钩子->下一动画帧去掉enter类并添加enter-to类
             * 执行beforeEnter钩子->添加enter,enter-active类并显示元素->执行enter钩子  是在同一个事件循环中同步执行的
             *
             * vue过渡leave顺序
             * 执行beforeLeave钩子->添加leave,leave-active类->执行leave钩子->下一动画帧去掉leave类并添加leave-to类
             */
        beforeEnter (el) {
          if (!this.transitioning) { // 从头开始，而不是leave取消了
            this.transitioning = true
            this.styleHeight = el.style.height
            this.styleDuration = el.style[durationName]
            this.styleTimingFunction = el.style[timingFunctionName]
            el.style.display = ''
            Object.assign(el.style, {
              height: window.getComputedStyle(el).height,
              [durationName]: `${this.duration}ms`,
              [timingFunctionName]: this.timingFunction
            })
          }
        },
        afterEnter (el) {
          this.transitioning = false
          Object.assign(el.style, {
            height: this.styleHeight,
            [durationName]: this.styleDuration,
            [timingFunctionName]: this.styleTimingFunction
          })
        },
        beforeLeave (el) {
          if (!this.transitioning) { // 从头开始，而不是enter取消了
            this.transitioning = true
            this.styleHeight = el.style.height
            this.styleDuration = el.style[durationName]
            this.styleTimingFunction = el.style[timingFunctionName]
            Object.assign(el.style, {
              height: window.getComputedStyle(el).height,
              [durationName]: `${this.duration}ms`,
              [timingFunctionName]: this.timingFunction
            })
          }
        },
        afterLeave (el) {
          this.transitioning = false
          Object.assign(el.style, {
            height: this.styleHeight,
            [durationName]: this.styleDuration,
            [timingFunctionName]: this.styleTimingFunction
          })
        }
      }
    }
</script>