ReloadEffect.js 2.28 KB
import '../../less/reload-effect.less'
import {randomString} from '@/utils/util'

// 修改数据特效
export default {
  props: {
    vNode: null,
    // 是否启用特效
    effect: Boolean,
  },
  data() {
    return {
      // vNode: null,
      innerEffect: false,
      // 应付同时多个特效
      effectIdx: 0,
      effectList: [],
    }
  },
  watch: {
    vNode: {
      deep: true,
      immediate: true,
      handler(vNode, old) {
        this.innerEffect = this.effect
        if (this.innerEffect && old != null) {
          let topLayer = this.renderSpan(old, 'top')
          this.effectList.push(topLayer)
        }
      },
    },
  },
  methods: {

    // 条件渲染内容 span
    renderVNode() {
      if (this.vNode == null) {
        return null
      }
      let bottom = this.renderSpan(this.vNode, 'bottom')
      // 启用了特效,并且有旧数据,就渲染特效顶层
      if (this.innerEffect && this.effectList.length > 0) {
        this.$emit('effect-begin')
        // 1.4s 以后关闭特效
        window.setTimeout(() => {
          let item = this.effectList[this.effectIdx]
          if (item && item.elm) {
            // 特效结束后,展示先把 display 设为 none,而不是直接删掉该元素,
            // 目的是为了防止页面重新渲染,导致动画重置
            item.elm.style.display = 'none'
          }
          // 当所有的层级动画都结束时,再删掉所有元素
          if (++this.effectIdx === this.effectList.length) {
            this.innerEffect = false
            this.effectIdx = 0
            this.effectList = []
            this.$emit('effect-end')
          }
        }, 1400)
        return [this.effectList, bottom]
      } else {
        return bottom
      }
    },
    // 渲染内容 span
    renderSpan(vNode, layer) {
      let options = {
        key: layer + this.effectIdx + randomString(6),
        class: ['j-vxe-reload-effect-span', `layer-${layer}`],
        style: {},
      }
      if (layer === 'top') {
        // 最新渲染的在下面
        options.style['z-index'] = (9999 - this.effectIdx)
      }
      return this.$createElement('span', options, [vNode])
    },
  },
  render(h) {
    return h('div', {
      class: ['j-vxe-reload-effect-box'],
    }, [this.renderVNode()])
  },
}