2017-11-11 264 views
0

我试图用vue.js制作一个计时器,但我遇到了一些问题。这是我的mtehods部分:两个问题:this.myMethod不是一个函数 - addEventListner添加的点击事件在用户点击时运行多于20次

methods: {   
    saveRunningMethod() { 
     var runningData = { 
      duration: `${this.hour} : ${this.minute} : ${this.second}`, 
      username: this.$store.state.user.username 
     } 
     this.$store.dispatch('saveRunning' , runningData) 
     console.log(runningData); 
    }, 
    startTimer(){  
     this.isTimerStart = true; 
     var timer = window.setInterval(() => { 

      var e = document.getElementById("stopBtn") 
      e.addEventListener("click", function(){ 
       clearInterval(timer) 
       this.isTimerStart = false; 
       console.log("lets Save it") 
       this.saveRunningMethod() 
       }); 

      if(this.mSecond < 9) 
       this.mSecond +=1 
      else 
       this.mSecond=0 

      if(this.mSecond==9) 
       this.second +=1     

      if(this.second>59)     
       this.second=0 

      if(this.second==59) 
       this.minute +=1 

      if(this.minute>59) 
       this.minute = 0 

      if(this.minute==59) 
       this.hour +=1    

    },100); 

    } 
} 

在这里,我e.addEventListener("click", function(){会停止计时器,当我点击我的停止按钮,但似乎这个方法运行多时间,因为你在这张图片上看到的,我的console.log运行33次!这是为什么?

enter image description here

我的其他问题,是关于这一行:this.saveRunningMethod()我跑我startTimer()方法中这种方法,但我得到"this.saveRunningMethod() is not a function"错误!

最后,你可以看到我用setInterval来制作一个计时器,如果你知道一个更好的解决方案,我会非常感激。

UPDATE:我补充我的html部分

<div class="row p-2 m-3 mt-3"> 
     <div class="col-12 p-0 animated fadeInUp mt-3"> 
      <p class="text-center">Your last record was : 00:00:00</p> 
     </div> 
     <div class="col-12 p-0 animated fadeInUp mt-3"> 
      <h1 class="text-center timer"> 
       {{this.hour}}:{{this.minute}}:{{second}}:{{mSecond}} 
      </h1> 
     </div> 
    </div> 
    <div class="row p-2 mt-3" v-bind:class="[this.isTimerStart==false ? 'show' : 'hide']"> 
     <div class="col-12 p-0 animated tada text-center"> 
      <button class="btn-link timerImg" @click="startTimer()"> 
       <img class="img-fluid timerImg" src="../../static/timerStart.png" /> 
       <p>Start</p> 
      </button> 
     </div> 
    </div> 

    <div class="row p-2 mt-3" v-bind:class="[this.isTimerStart ? 'show' : 'hide']"> 
     <div class="col-12 p-0 animated tada text-center"> 
      <button id="stopBtn" class="btn-link timerImg"> 
       <img class="img-fluid timerImg" src="../../static/timerStop.png" /> 
       <p>Stop</p> 
      </button> 
     </div> 
    </div> 

谢谢。

+0

从你的代码是不明确的,为什么是定时器运行的多发时期。编辑问题并添加HTML部分。 – WaldemarIce

+0

@WaldemarIce我的html部分只是一个显示计时器和两个按钮的div,我更新了问题并添加了它。谢谢。 –

+0

请一次提出一个问题。 https://stackoverflow.com/help/how-to-ask – Rob

回答

1

According to MDN,这是window.setInterval()做:

重复调用的函数,每次调用该函数之间的固定时间延迟。

所以执行您的startTimer()方法时,它被添加click事件监听到你停止按钮每100毫秒。所以,如果你加载页面,点击停止按钮之前等待3.3秒,该click事件监听器将被添加到按钮33倍:

var timer = window.setInterval(() => { 

    var e = document.getElementById("stopBtn") 
    e.addEventListener("click", function() { 
     // This code will execute 33 times when the stop button is clicked. 
    }) 
    ... 
}, 100) 

如果您加载网页并等待5.4秒单击停止前按钮,click事件监听器将被添加到按钮54次!

而不是使用window.setInterval()你应该使用window.setTimeout()According to MDN,这是它的作用:

在指定的延迟后执行代码段或函数。

换句话说,window.setTimeout()会创建一个计时器,该计时器只能在您指定的延迟后运行一次。

至于错误this.saveRunningMethod() is not a function,你的上下文传递给addEventListener()的回调函数内改变,所以this值变为按钮本身,而不是你的对象。为了避免这种情况,您可以将箭头函数传递给addEventListener()。这将使得环境保持不变(所以箭头函数内部的this值将保持你的对象):

window.setTimeout(() => { 
    var e = document.getElementById("stopBtn") 
    e.addEventListener("click",() => { 
     this.isTimerStart = false; 
     console.log("lets Save it"); 
     this.saveRunningMethod(); 
    }); 
}, 100) 
+0

感谢您的回答,它解释了一切,我想我需要找到另一种方法来创建一个计时器,因为setTimeout无法通过setInterval实现。同时将箭头函数添加到addEventListener()解决了我的第二个问题。 –