【问题标题】:Vue equivalent of setTimeout?Vue相当于setTimeout?
【发布时间】:2016-11-18 20:06:03
【问题描述】:

我正在使用 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;
            }

(是的,我很快会在 then-catch 中添加这个)。

这工作正常并出现消息。但是,我希望消息在一段时间后再次消失,比如几秒钟。我怎样才能用 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);
            }

【问题讨论】:

  • 试试setTimeout(()=&gt;{ this.basketAddSuccess = false; }, 2000);
  • 很可能,setTimeout 中的this 并不指向主对象。
  • @akinuri 使用 ES6 和箭头函数 this 应该指的是正确的范围。这是典型的var self=this 解决之前的问题。如果我错了,请纠正我。未测试。

标签: javascript vue.js


【解决方案1】:

箭头函数

解决这个问题最好和最简单的方法是使用箭头函数() =&gt; {}

    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 在Vue 中是bound to the this of its enclosing scope-,它是父/封闭组件。但是,在 setTimeout 调用的传统函数中,this refers to the window object (这就是为什么您在该上下文中尝试访问 this.basketAddSuccess 时遇到错误的原因)。

参数传递

另一种方法是将this 作为参数通过setTimeout's prototype 使用其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绑定到setTimeout之外的一个var:

    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);
    }

使用箭头函数将完全消除对这个额外变量的需求,并且确实应该使用,除非有其他东西阻止它的使用。

【讨论】:

  • 这里应该使用箭头函数而不是使用self来引用this
  • 如果用户同时更改了组件/页面,而当前(this/self...)组件被销毁了怎么办?
  • 如果你需要更复杂的行为处理,有超时/等待,取消处理,换页,去抖动,ecc。最好使用 RxJS 或类似的东西。你可以从这里开始:rxmarbles.com
  • 箭头功能在IE11及以下版本不起作用。后两种解决方案可以。
  • 好吧,你知道吗 - 箭头函数对我有用,而不是常规函数 :)
【解决方案2】:

在遇到同样的问题后,我结束了这个线程。为了下一代:当前投票最多的答案,尝试将“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);
    }

【讨论】:

    【解决方案3】:

    将 bind(this) 添加到您的 setTimeout 回调函数

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

    【讨论】:

      【解决方案4】:

      ES6 可以绑定 'this'

      setTimeout(() => {
      
       },5000);
      
      

      【讨论】:

        【解决方案5】:

        vuejs 2

        首先将其添加到方法中

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

        之后在mounted上调用这个方法

        mounted () {
          this.sayHi()
        }
        

        【讨论】:

          【解决方案6】:

          你可以使用 Vue.nextTick

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

          【讨论】:

          • 你可以将nexTick包裹在setTimeout下
          【解决方案7】:

          上面的 Kevin Muchwat 给出了最好的答案,尽管只有 10 个赞成票并且没有选择答案。

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

          让我解释一下为什么。

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

          然而,微软以其无限的智慧决定 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 属性/函数时出现问题)

          【讨论】:

          • 随着 Edge 迁移到 Chromium,很快这将不再是问题(最终)
          • @dave 不确定当 IE 不支持这一点时,这有何不同。 Edge 自 2015 年以来一直支持这一点。
          • 而且你总是可以使用像 babel 这样的 EcmaScript 转译器来将你的箭头函数转换为支持 IE。
          【解决方案8】:

          箭头函数

          解决这个问题最好和最简单的方法是使用箭头函数() =&gt; {}

              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 在Vue 中是bound to the this of its enclosing scope-,它是父/封闭组件。然而,在 setTimeout 调用的传统函数中,this refers to the window object (这就是为什么您在该上下文中尝试访问 this.basketAddSuccess 时遇到错误的原因)。

          参数传递

          另一种方法是通过setTimeout's prototype 使用setTimeout(callback, delay, arg1, arg2, ...) 形式将this 作为arg 传递给您的函数:

              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 及以下版本不兼容。)

          【讨论】:

            【解决方案9】:

            使用箭头函数时不需要bind(this)

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

            【讨论】:

              【解决方案10】:

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

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

              【讨论】:

                【解决方案11】:

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

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

                【讨论】:

                  【解决方案12】:

                  这可能是范围问题。请尝试以下方法:

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

                  【讨论】:

                    【解决方案13】:

                    请像下面这样使用 setInterval:

                        setInterval(()=>{this.checkOrder()},2000);
                    

                    【讨论】:

                      猜你喜欢
                      • 2016-02-14
                      • 2021-08-13
                      • 2022-01-01
                      • 2019-07-28
                      • 1970-01-01
                      • 2011-06-16
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-01-19
                      相关资源
                      最近更新 更多