前几天遇见一个棘手的问题,简单来说,在vue实例中用v-if控制a组件的显现/隐藏,当a隐藏后,我在其内部设置的setInterval依旧会执着地执行。。一番折腾后,发现了其中的原因:
当组件移除/router切换时,组件确实已经被摧毁了,如果在created钩子函数里添加输出,可以看到每次重新加入/切换回来的时候都会触发,其实,这与组件的机制无关。
setInterval/setTimeout相当于你申请的一种资源,在指定的时间后/时间间隔中执行指定的操作,只能由你手动释放。
setTimeout 指定时间后将任务放进任务队列,在引擎空闲时执行;
setInterval 每隔一段时间将任务放入任务队列;
接下来通过几个实例来剖析一下定时器的原理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> </body> <script> var a= setTimeout(()=>{ alert(1) },2000) console.log(a) //1 clearTimeout(a) document.write(a)//1 //多次设置,累加 a= setTimeout(()=>{ alert(1) },2000) clearTimeout(a) document.write(a) //2 </script> </html>
分析:当创建一个定时器时,会返回一个ID作为其唯一标示,这就是type of(定时器)为number的原因,随着更多定时器的调用ID累加
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> </body> <script> var a= setTimeout(()=>{ alert(1) },2000) a= undefined //定时器依旧有效 document.write(a) //undefined setTimeout(()=>{ console.log(a) //undefined },4000) </script> </html>
剖析:清除定时器的唯一方法是clearTimeout/clearInterval,即使将定时器设为undefined,也只是改变了a的值,请求的资源依旧存在!
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> </body> <script> var a= setTimeout(()=>{ alert(1) }, 1000) a= setTimeout(()=>{ alert(2) }, 1100) //重复设置会累加!因此得先清除 </script> </html>
剖析:重复定义的不会覆盖之前申请的资源,这也是重复设置setInterval会越来越快的原因,之前请求的资源依旧有效!
额外的补充->当我们在项目中定义了许多的定时器,如何一次性清除?可参考:https://www.cnblogs.com/daysme/p/6428439.html