1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
| 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()])
| },
| }
|
|