我遇到了Vue.js的问题,其中nextTick()
似乎无法正常工作。
我有以下HTML代码
<q-icon
color='grey-7'
:name="connectionStateIcon"
class="icon-reconnect"
:class='[$storage.state.websocket.state, reconnect_pulse]'></q-icon>
其中connectionStateIcon
是一个计算属性,用于选择当前连接状态的图标,$storage.state.websocket.state
保留了将要使用的当前连接状态(打开,关闭...)的文本表示形式选择一个css定义(即.q-icon.icon-reconnect.open
)以将某种基础颜色应用于图标,并且reconnect_pulse
是一个data
变量,用于触发动画。
无论何时触发新的重新连接尝试,都应运行动画,并且reconnect_pulse
应该从类''
过渡到'reconnectpulse'
以便触发动画。
data: function () {
return {
reconnect_pulse: '',
}
},
created() {
this.$eventbus.$on('connection-state', (state) => {
if (state == 'reconnecting') {
this.reconnect_pulse = ''; // remove the class `reconnectpulse`
this.$nextTick(() => { this.reconnect_pulse = 'reconnectpulse'; }); // add the class `reconnectpulse` to trigger the animation
//setTimeout(() => { this.reconnect_pulse = 'reconnectpulse'; }, 100) // this works, and more reliably, the bigger the timeout is.
}
})
},
CSS如下:
@keyframes reconnectpulse {
from { color:#ffa000; } to { } /* from orange to whichever base color the icon has */
}
.q-icon.reconnectpulse {
animation: reconnectpulse 2.0s ease-in; /* the above animation's properties */
}
.q-icon.icon-reconnect { } /* "grey-7" is default base color */
.q-icon.icon-reconnect.open {
color: yellowgreen; /* when the connection is established, select green as the base color */
}
我的问题是我假设this.$nextTick
的代码将在Vue完成执行已删除CSS类reconnectpulse
的当前滴答后立即执行,因此下一个刻度reconnectpulse
可以再次应用,然后DOM将触发动画。
但是由于某种原因,它只能运行一次。如果我将this.$nextTick
替换为setTimeout
,并且超时时间相对较长,那么在重新应用该元素之前,该元素已将其类reconnectpulse
删除了足够长的时间,那么它将起作用。超时为20毫秒时,有时仅有时为0毫秒(因为reconnect_pulse
的初始值为''
)只有一次,而有时只有100毫秒。
非常奇怪的是,我当前正在重写Vue组件,而旧版本的setTimeout
为0ms,并且每次都能工作。我不知道到底有什么区别,因为旧代码有些混乱,但是从本质上讲,有关动画的代码是相同的。
我期望this.$nextTick
能够以非常精确的方式替换setTimeout
,但是它不起作用,而且我不擅长手动调整setTimeout
延迟,因为这可能会因设备而异。
在这种情况下this.$nextTick
有什么问题?在不使用setTimeout
的情况下,我还能做什么来存档所需的效果?
直接访问元素时同样如此:
_.forEach(document.querySelectorAll('.icon-reconnect'), (icon) => {
icon.classList.remove('reconnectpulse')
})
setTimeout(() => {
_.forEach(document.querySelectorAll('.icon-reconnect'), (icon) => {
icon.classList.add('reconnectpulse')
})
}, 100)
然后我期望以下内容可以工作(但没有):
_.forEach(document.querySelectorAll('.icon-reconnect'), (icon) => {
icon.classList.remove('reconnectpulse')
icon.classList.add('reconnectpulse')
})
答案 0 :(得分:0)
一种解决方案是在重新应用该类之前不清除该类,而是将其替换为具有相同动画属性的另一个类。
<q-icon
color='grey-7'
:name="connectionStateIcon"
class="icon-reconnect"
:class='[$storage.state.websocket.state, reconnect_pulse]'></q-icon>
data: function () {
return {
reconnect_pulse: '',
}
},
created() {
this.$eventbus.$on('connection-state', (state) => {
if (state == 'reconnecting') {
if (this.reconnect_pulse != 'reconnect-pulse-tick') {
this.reconnect_pulse = 'reconnect-pulse-tick'
}
else {
this.reconnect_pulse = 'reconnect-pulse-tock'
}
}
})
},
@keyframes reconnect-pulse-tick {
from { color:#ffa000; } to { }
}
.q-icon.reconnect-pulse-tick {
animation: reconnect-pulse-tick 2.0s ease-in;
}
@keyframes reconnect-pulse-tock {
from { color:#ffa000; } to { }
}
.q-icon.reconnect-pulse-tock {
animation: reconnect-pulse-tock 2.0s ease-in;
}
.q-icon.icon-reconnect { } /* "grey-7" is default base color */
.q-icon.icon-reconnect.open {
color: yellowgreen; /* when the connection is established, select green as the base color */
}
在这种情况下,动画关键帧还必须具有不同的名称,这一点很重要,如上面的CSS代码所示。
TBH,我实际上更喜欢此解决方案,而不是尝试使用nextTick
或setTimeout
的解决方案。