H E L L O W O R L D

20181111 计时器影响DOM点击事件的逻辑

今天在群里看见一个人在问"点击按钮使图片产生旋转为什么要使用计时器来实现",我自己操作了一遍她的代码才发现里面的逻辑实现很有意思,所以写出来分享一下。

她的代码是这样写的:

 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <title>Page Title</title>
 5         <style>
 6             #myImg {
 7                 width: 60%;
 8             }
 9             .myShow {
10                 animation: rotate 1s;
11             }
12             @keyframes rotate {
13                 ftom {transform: rotate(0deg);}
14                 to {transform: rotate(180deg);}
15             }
16         </style>
17     </head>
18     <body>
19         <div>
20             <img
21                 id='myImg'
22                 src='http://www.8090.com/uploads/allimg/141204/3-141204134GJ95.jpg'
23             />
24             <p id='demo'></p>
25             <button onclick='myBtn()'>click</button>
26         </div>
27         <script>
28             function myBtn() {
29                 var rotate = document.getElementById('myImg');
30                 var myAttr = function(){
31                     rotate.setAttribute('class','myShow');
32                 }
33                 setTimeout(myAttr,30);
34                 rotate.setAttribute('class','');
35             }
36             
37         </script>
38     </body>
39 </html>

在这里,通过点击按钮触发myBtn函数,先执行计时器setTimeout, 调用myAttr函数添加了class属性'myShow',再移除了这个class属性。和‘myShow'绑定了rotate这个CSS动画,从而实现图片旋转。

 

回到她的问题:"为什么要使用计时器来实现图片旋转?"

按照她的想法,不使用计时器,只要再次点击按钮,不一样会产生click事件么,那计时器有什么用?

 

下面去掉计时器,直接使用setAttribute属性看看是否可以达到同样效果。js代码如下:

 1 <script>
 2     function myBtn() {
 3         var rotate = document.getElementById('myImg');
 4       //  var myAttr = function(){
 5       //      rotate.setAttribute('class','myShow');
 6       //      console.log('hello')
 7       //  }
 8         rotate.setAttribute('class','myShow');
 9       //  setTimeout(myAttr,30);
10         rotate.setAttribute('class','');
11     }
12     
13 </script>

然而,点击按钮没有产生任何反应。原因是因为js的运行逻辑是至上而下的顺序,当我们点击按钮后,myBtn函数从上而下执行,执行完后class属性已被删除,就不会对HTML产生DOM效果。

那同样在前面的代码里,js函数的最后一行也是rotate.setAttribute('class',''),为什么可以正常产生DOM效果?

通过加入console.log后,我发现计时器的原理是它改变了函数的运行顺序。

通过添加计时器,函数的执行顺序变成了:’执行setTimeout方法' => ‘删除class属性' => (30毫秒后)'添加class属性'。因为函数的运行结果是添加class属性,所以保留了class='myShow',从而引用了CSS动画效果。

 1 <script>
 2     function myBtn() {
 3         var rotate = document.getElementById('myImg');
 4         var myAttr = function(){
 5             rotate.setAttribute('class','myShow'); //设置class属性值为myShow
 6             console.log(document.getElementById('myImg').className)
 7         }
 8         setTimeout(myAttr,30);
 9         rotate.setAttribute('class','None'); //设置class属性值为None
10         console.log(document.getElementById('myImg').className)
11     }
12     
13 </script>

执行页面后,发现console.log打印结果先是'None',再是'myShow',说明了每次点击按钮都是先"删除"class属性,在添加class属性。这样每次className都是被保留了下来,而再次点击按钮,则又先删掉了class属性,以此类推。

 

posted on 2018-11-11 17:32  chenko  阅读(248)  评论(0)    收藏  举报