【问题标题】:Vue $emit not getting executed in finally()Vue $emit 没有在 finally() 中执行
【发布时间】: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() 的目的是不必复制代码。

  1. 为什么this.$emit('toggle-load-overlay', false) 在我当前代码的finally() 中不起作用?
  2. 为什么它在 then/catch 中起作用?
  3. 有没有办法让它在finally() 中也能工作?

【问题讨论】:

  • 你能创建一个minimal reproducible example 来重现这个错误吗?如果您需要基于多文件节点的环境,请使用 codesandbox.io,如果您可以使用 umd 导入(cdn 脚本)将其包装起来,请使用基本的Stack Overflowsn-p。您确定您的 Promise 实现有finally()(并非所有人都这样做)。

标签: vue.js promise fetch


【解决方案1】:

它正在工作,如果正在处理事件,你能检查你的父组件吗

请不要:这是测试 $emit 最终是否有效的通用解决方案。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.js"></script>
</head>
<body>
    <div id="app">
        <div v-if="loading">Loading...</div>
        <test @set-loader="setLoader"></test>
    </div>

    <script>
        Vue.component('test',{
            template:'<div>Hi</div>',
            mounted:function(){
                fetch('https://jsonplaceholder.typicode.com/todos/1')
                .then(response => response.json())
                .then(json => console.log(json))
                .finally(() => {
                    console.log('child finally');
                    this.$emit('set-loader', false);
                });

            }
        });
        new Vue({
            el:'#app',
            data:{
                loading:true
            },
            methods:{
                setLoader: function(value){
                    console.log('parent event');
                    console.log(value);
                    this.loading = value;
                }
            }
        });
    </script>
</body>
</html>

【讨论】:

  • 如果你投了反对票,你需要说出原因而不是默默地去做。
猜你喜欢
  • 2019-04-05
  • 2012-12-25
  • 1970-01-01
  • 2020-03-18
  • 2016-11-03
  • 2017-01-12
  • 2020-07-30
  • 2013-03-14
  • 1970-01-01
相关资源
最近更新 更多