Vue等价于setTimeout吗?


80

我正在使用Laravel和Vue制作购物车系统。当我将商品添加到购物篮中时,我会通过切换由v-if监视的Vue变量来显示确认消息:

<div class="alert alert-success" v-if="basketAddSuccess" transition="expand">Added to the basket</div>

和JS:

addToBasket: function(){
                item = this.product;
                this.$http.post('/api/buy/addToBasket', item);
                this.basketAddSuccess = true;
            }

(是的,我很快就会在随后的内容中添加它)。

这可以正常工作,并显示消息。但是,我希望该消息在一定时间(例如几秒钟)后再次消失。如何使用Vue做到这一点?我尝试过,setTimeOut但是Vue似乎不喜欢它,说它是不确定的。

编辑:我setTimeout像一个白痴一样拼错。但是,它仍然不起作用:

我的功能现在是:

addToBasket: function(){
                item = this.photo;
                this.$http.post('/api/buy/addToBasket', item);
                this.basketAddSuccess = true;
                setTimeout(function(){
                    this.basketAddSuccess = false;
                }, 2000);
            }

8
尝试setTimeout(()=>{ this.basketAddSuccess = false; }, 2000);
亚历山大·法卡斯(Alexander Farkas)2016年

3
可能this在内部setTimeout不指向主要对象。
akinuri '16

@alexanderfarkas这个工程,谢谢!
flurpleplurple

@akinuri使用ES6和箭头功能this应指向正确的范围。这是典型的解决方案之前的问题var self=this。如果我错了,请纠正我。未经测试。
ibsenleo

回答“ Vue等于setTimeOut吗?”会很酷。-但是在setTimeout情况下,我们有一组常规的“是如何工作的”答案。我仍在寻找专门使用Vue的答案-而不是将事件移交给堆栈。
sheriffderek

Answers:


111

箭头功能

解决此问题的最好,最简单的方法是使用箭头功能() => {}

    addToBasket() {
        var item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        // now 'this' is referencing the Vue object and not the 'setTimeout' scope
        setTimeout(() => this.basketAddSuccess = false, 2000);
    }

之所以可行,this是因为arrow函数绑定到了this它的封闭范围-在Vue中,它是父/封闭组件。setTimeout但是,thiswindow由调用的传统函数内部是对象(这就是为什么您尝试this.basketAddSuccess在该上下文中访问时遇到错误的原因)。

参数传递

这样做的另一种方式是通过this作为对Arg的你的函数通过setTimeout的原型使用它的setTimeout(callback, delay, arg1, arg2, ...)形式:

    addToBasket() {
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        //Add scope argument to func, pass this after delay in setTimeout
        setTimeout(function(scope) {
             scope.basketAddSuccess = false;
        }, 2000, this);
    }

(值得注意的是,arg传递语法与IE 9及以下版本不兼容。)

局部变量

另一种可能但又不太雄辩且不那么鼓励的方法是绑定this到var之外的var setTimeout

    addToBasket() {
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        //Declare self, which is accessible inside setTimeout func
        var self = this;
        setTimeout(function() {
             self.basketAddSuccess = false;
        }, 2000);
    }

但是,使用箭头功能将完全不需要此额外变量,并且除非有其他原因阻止使用它,否则应真正使用它。


17
这应该使用箭头功能而不是使用self来指代
glaba '18

如果用户同时更改组件/页面并且当前(this / self ...)组件被破坏怎么办?
robert.little

如果您需要更复杂的行为处理,包括超时/等待,取消处理,更改页面,反跳,ecc。最好使用RxJS之类的东西。您可以在这里开始:rxmarbles.com
g.annunziata

箭头功能在IE11及以下版本中不起作用。后两种解决方案可以。
—LubošMiřatský20年

96

遇到相同的问题后,我结束了这个话题。为了子孙后代:当前最投票表决的答案,尝试将“ this”绑定到变量,以避免在调用setTimeout中定义的函数时更改上下文。

另一种推荐的替代方法(使用Vue.JS 2.2和ES6)是使用箭头功能,以便将上下文绑定到父对象(基本上是“ addToBasket”的“ this”和“ setTimeout”的“ this”仍将引用同一对象):

addToBasket: function(){
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        setTimeout(() => {
            this.basketAddSuccess = false;
        }, 2000);
    }

2
“为了子孙后代”!
法比奥ZC



4

您可以使用Vue.nextTick

addToBasket: function(){
                item = this.photo;
                this.$http.post('/api/buy/addToBasket', item);
                this.basketAddSuccess = true;
                Vue.nextTick(() =>{
                    this.basketAddSuccess = false;
                });
            }

即使它奏效了,也会立即关闭div。
gurghet

您可以在setTimeout下包装nexTick
Samundra Khatri

2
@SamundraKhatri如果您回答了问题,而不是在评论中说“您可以按照问题的要求去做”,则可能会得到答案的投票权。
贾里德·瑟斯克

4

vuejs 2

首先将此添加到方法

methods:{
    sayHi: function () {
      var v = this;
      setTimeout(function () {
        v.message = "Hi Vue!";
    }, 3000);
   }

之后,在挂载上调用此方法

mounted () {
  this.sayHi()
}

4

尽管只有10次投票且未选择答案,但上述Kevin Kevin还是最佳答案。

setTimeout(function () {
    this.basketAddSuccess = false
}.bind(this), 2000)

让我解释为什么。

“箭头功能”是ECMA6 / ECMA2015。它在已编译的代码或受控制的客户端情况(cordova电话应用程序,Node.js)中非常有效,而且简洁明了。它甚至可能会通过您的测试!

但是,Microsoft以其无穷的智慧决定Internet Explorer将永远不会支持ECMA2015!

他们的新Edge浏览器可以,但是对于面向公众的网站来说还不够。

执行标准function(){}并添加.bind(this)是ECMA5.1(完全受支持)语法,用于完全相同的功能。

这在ajax / post .then / else调用中也很重要。在.then(function){})的末尾,您还需要在那里绑定(this):.then(function(){this.flag = true} .bind(this))

我本来可以将此添加为对Kevin的回复的评论,但出于某些愚蠢的原因,发表回复要比评论评论花费更少的积分

不要犯同样的错误!

我在Mac上进行编码,并使用了48分赞成的评论,效果很好!直到我对脚本的一些调用失败并且我不知道为什么。我不得不回去并将数十个调用从箭头语法更新为function(){}。bind(this)语法。

值得庆幸的是,我再次找到了该线程并获得了正确的答案。凯文,我永远感激不已。

按照“已接受的答案”,还有其他潜在的问题需要处理其他库(在正确访问/更新Vue属性/功能时遇到了问题)


2
随着Edge移至Chromium,很快就不会成为一个问题了(最终)
dave

分手后要往前看了。:)
sheriffderek

1
@dave不知道当IE不支持此参数时,这有什么区别。自2015
。– FINDarkside '19

而且,您始终可以使用像babel这样的EcmaScript编译器来将箭头函数转换为支持IE。
A1rPun

3

bind(this)使用箭头功能时不需要:

  setTimeout( ()=> {
    // some code
   }, 500)

3

如果要在函数中使用this关键字,则需要在ES6中编写setTimeout函数

setTimeout(() => {
   this.filters.max_budget_gt_eq = this.budgetHigherValue;
}, 1000);

3

箭头功能

解决此问题的最好,最简单的方法是使用箭头功能() => {}

    addToBasket() {
        var item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        // now 'this' is referencing the Vue object and not the 'setTimeout' scope
        setTimeout(() => this.basketAddSuccess = false, 2000);
    }

之所以可行,this是因为arrow函数绑定到了this它的封闭范围-在Vue中,这是父/封闭组件。setTimeout但是,thiswindow由调用的传统函数内部引用了该对象(这就是为什么您尝试访问时会遇到错误的原因this.basketAddSuccess在该上下文中)。

参数传递

这样做的另一种方式是通过this作为对Arg的你的函数通过setTimeout的原型使用它的setTimeout(callback, delay, arg1, arg2, ...)形式:

    addToBasket() {
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        //Add scope argument to func, pass this after delay in setTimeout
        setTimeout(function(scope) {
             scope.basketAddSuccess = false;
        }, 2000, this);
    }

(值得注意的是,arg传递语法与IE 9及以下版本不兼容。)


0

使用this.animationStop,不使用this.animationStop ()

animationRun(){
    this.sliderClass.anim = true;
    setTimeout(this.animationStop, 500);
},

0

这可能是范围问题。请尝试以下操作:

addToBasket: function(){
    item = this.photo;
    this.$http.post('/api/buy/addToBasket', item);
    this.basketAddSuccess = true;
    var self = this;
    setTimeout(function(){
        self.basketAddSuccess = false;
    }, 2000);
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.