【发布时间】:2020-11-28 20:58:47
【问题描述】:
在LoginForm.vue我有这个功能:
login() {
event.preventDefault();
let data = {
email : this.email,
password : this.password
};
if(this.remember)
data['remember'] = 'on';
this.$emit('toggle-load-overlay', true);
fetch(this.loginRoute, {
method : 'POST',
body : JSON.stringify(data),
headers : {
"Content-Type": "application/json; charset=utf-8",
'X-CSRF-TOKEN' : this.csrf,
},
})
.then(data => data.json())
.then(data => {
if(!data['success'])
this.errors = data['errors'];
else {
this.csrf = data['csrf'];
this.$emit('loggedin', data['user']);
this.$emit('update-token', data['csrf']);
}
})
.catch(error => console.log(error))
.finally(() => {
this.$emit('toggle-load-overlay', false);
});
}
在获取之前,我通过向我的AuthComponent.vue - this.$emit('toggle-load-overlay', true); 发送一个事件,在屏幕上放置了一个加载覆盖层
在AuthComponent.vue 中,事件处理程序如下所示:
toggleLoadOverlay(displayOverlay) {
this.isLoading = displayOverlay;
}
第一个发射被执行并覆盖。然后,在finally() 中,我尝试再次发出相同的事件以隐藏覆盖。但它不会被执行。我调试了它,它进入了finally(),但是emit没有被执行。
另外,我观察到 $emit 方法内部发生了什么:
Vue.prototype.$emit = function (event) {
var vm = this;
{
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
var info = "event handler for \"" + event + "\"";
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info);
}
}
return vm
};
我注意到这两种发射之间的一个区别。在这一行中,var cbs = vm._events[event]vm._events 在第一次发出时不是空的(它有事件toggleLoadOverlay),而在第二次发出时它是空的。
另一个观察结果是,第二次发出在最终的then() 语句中起作用。所以现在我会把它放在那里,以及catch()。但finally() 的目的是不必复制代码。
- 为什么
this.$emit('toggle-load-overlay', false)在我当前代码的finally()中不起作用? - 为什么它在 then/catch 中起作用?
- 有没有办法让它在
finally()中也能工作?
【问题讨论】:
-
你能创建一个minimal reproducible example 来重现这个错误吗?如果您需要基于多文件节点的环境,请使用 codesandbox.io,如果您可以使用 umd 导入(cdn 脚本)将其包装起来,请使用基本的Stack Overflowsn-p。您确定您的 Promise 实现有
finally()(并非所有人都这样做)。