【问题标题】:Vue Transition - JavaScript hooksVue 转换 - JavaScript 钩子
【发布时间】:2019-10-25 11:59:56
【问题描述】:
基于this answer,我正在尝试使用转换创建一个Vue slideToggle组件。
slideToggle 是高度动画中的经典范例。到目前为止,我已经成功了...
我不想设置固定的max-height 或height,我希望height 是动态的。
我的动画在显示和隐藏时工作正常。问题在于显示或隐藏时取消。
如何处理@enter-cancelled 和@leave-cancelled 钩子?我是 vue 转换的新手 :)
我将我的代码放在这个 CodeSandBox 中:https://codesandbox.io/s/vue-template-3b7oj
【问题讨论】:
标签:
javascript
vue.js
vue-component
【解决方案1】:
Vue-Transition-取消
tl;dr
- 离开事件取消尚未调用进入
- enter 取消尚未调用 leave
取消状态存储在
-
el._enterCb.cancelled
-
el._leaveCb.cancelled
分析
考虑:
const cb = el._enterCb = once(() => {
if (expectsCSS) {
removeTransitionClass(el, toClass)
removeTransitionClass(el, activeClass)
}
if (cb.cancelled) {
if (expectsCSS) {
removeTransitionClass(el, startClass)
}
enterCancelledHook && enterCancelledHook(el)
} else {
afterEnterHook && afterEnterHook(el)
}
el._enterCb = null
})
来源:_enterCb
所以取消@enter 的幼稚解决方案是
el => {el._enterCb.cancelled = true; done()}
这就是触发leave 时实际发生的情况
// call enter callback now
if (isDef(el._enterCb)) {
el._enterCb.cancelled = true
el._enterCb()
}
来源:leave
同样适用于:
const cb = el._leaveCb = once(() => {
if (el.parentNode && el.parentNode._pending) {
el.parentNode._pending[vnode.key] = null
}
if (expectsCSS) {
removeTransitionClass(el, leaveToClass)
removeTransitionClass(el, leaveActiveClass)
}
if (cb.cancelled) {
if (expectsCSS) {
removeTransitionClass(el, leaveClass)
}
leaveCancelled && leaveCancelled(el)
} else {
rm()
afterLeave && afterLeave(el)
}
el._leaveCb = null
})
来源:_leaveCb
可以检查可能的分配:
https://github.com/vuejs/vue/search?q=_leaveCb&unscoped_q=_leaveCb
【解决方案2】:
根据官方文档Javacript transition hooks
@leave-cancelled 仅适用于 v-show,在您使用 v-if 的示例代码中,如果您更改此设置,您将能够捕获 @leave-cancelled 钩子、@leave-cancelled 和 @enter -cancelled 在进入或离开被中断时触发,例如在打开时按下切换按钮以及在关闭时按下按钮。
【解决方案3】:
我不知道这是否对你有帮助,但试试这个:
声明一个新变量:
data() {
return {
height: null,
toggling: false
};
},
当开启或关闭函数启动时,验证toggling是否为真,如果是则取消,如下:
enter(el) {
if (this.toggling) return;
this.toggling = true;
this.height = el.offsetHeight;
el.style.overflow = "hidden";
el.style.height = 0;
el.style.paddingTop = 0;
el.style.paddingBottom = 0;
el.style.marginTop = 0;
el.style.marginBottom = 0;
setTimeout(() => {
el.style.transitionProperty = `height, margin, padding`;
el.style.transitionDuration = this.duration + "ms";
el.style.height = this.height + "px";
el.style.removeProperty("padding-top");
el.style.removeProperty("padding-bottom");
el.style.removeProperty("margin-top");
el.style.removeProperty("margin-bottom");
this.toggling = false;
});
},
会是这样的:
https://codesandbox.io/s/vue-template-78n7t?fontsize=14
也许我破坏了你的代码,抱歉,但你能明白吗?