码迷,mamicode.com
首页 > Web开发 > 详细

一道原生js题目引发的思考(鼠标停留区块计时)

时间:2014-11-04 19:32:35      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   使用   java   sp   

我瞎逛个啥论坛,发现了一个题目,于是本着练手的心态就开始写起来了,于是各种问题接踵而至,收获不小。

题目是这样的:

bubuko.com,布布扣

刚看上去,没什么特别,心里想了,我就用mouseover和mouseout事件,然后绑个定时器不就行了嘛~.......于是还没开始写呢,就被问到了,那mouseover和mouseenter这两个事件有什么区别的?为什么不用mouseenter呢?

然后我就仔细想了下mouseover和mouseenter之间的区别,下面是书上列出的定义:

 

->mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发,这个事件不冒泡。而且在光标移到它后代元素上时不会触发;

->mouseover:在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内时触发。

 

mouseleave与mouseout与上面enter和over大致相同的,我觉得说白了,就是冒泡与不冒泡的区别,下面这儿有个例子,看起来就特别明显啦:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset=utf-8>
 5 <title>mouseover与mouseenter的区别demo</title>
 6 <style type="text/css">
 7   
 8 </style>
 9 </head>
10 <body>
11     <span>mouseenter的效果:</span>
12     <ul id="testEnter">
13       <li>item 1</li>
14       <li>item 2</li>
15       <li>item 3</li>
16     </ul> 
17     <span>mouseover的效果:</span>
18     <ul id="testOver">
19       <li>item 1</li>
20       <li>item 2</li>
21       <li>item 3</li>
22     </ul>     
23     <script>
24         
25         var test = document.getElementById("test");
26 
27         
28         testEnter.addEventListener("mouseenter", function( event ) {   
29         
30           event.target.style.color = "red";
31 
32           setTimeout(function() {
33             event.target.style.color = "";
34           }, 500);
35 
36         }, false);
37         
38         testOver.addEventListener("mouseover", function( event ) {   
39          
40           event.target.style.color = "orange";
41 
42           setTimeout(function() {
43             event.target.style.color = "";
44           }, 500);
45 
46         }, false);
47          
48     </script>
49 </body>  
50 </html>

 

更明显的观察区别,猛戳这里:mouseenter与mouseover区别demo

 

恩,于是根据自己的题目,我就选择了mouseover和mouseout,其实demo比较简单,这里看似并无大碍;

于是我的第一个版本出炉啦~~:

 

56     <script type="text/javascript">
57          var counter = 0,
58              counter1 = 0,
59              counter2 = 0,
60              counter3 = 0;
61          var timer = null;
62          function timerCounter(div,counter,num){
63              div.addEventListener(mouseover,function(){
64                 timer = setInterval(count,1000);             
65              },false); 
66             div.addEventListener(mouseout,function(){
67              clearInterval(timer);
68              //这里设置null是很有必要的,为了重复计数
69              timer = null;
70              },false);
71             var span = document.createElement(span);
72             div.appendChild(span);
73             function count(){
74                 counter++;
75                 span.innerHTML = STAY:+counter;
76                 console.log(区块+num+上停留的时间为:+counter);
77             } 
78             return counter;
79          }
80           var div = document.getElementsByTagName(div);
81           timerCounter(div[0],counter1,div[0].dataset[spmid]);
82           timerCounter(div[1],counter2,div[1].dataset[spmid]);
83           timerCounter(div[2],counter3,div[2].dataset[spmid]);        
84     </script>

 

看它的运行结果,猛戳这里:区块停留计数器第一个版本

一直在chrome下测试, 运行成功了,暂且高兴会儿,想个别的办法,好像用Date对象也可以实现,于是没费什么事儿,在我的chrome里,他也可以计数了,唯一不足的就是他要鼠标离开后才显示秒数,不过我没计较,因为潜意识里面意识到了我的代码很水,但还是先把它实现放上来看看:

 

56     <script type="text/javascript">
57          var startTime = 0,
58              totalTime = 0,
59              stayTime = 0,
60              counter1 = 0,
61              counter2 = 0,
62              counter3 = 0;
63          var timer = null;
64          function timerCounter(div,startTime,totalTime,num){
65              var span = document.createElement(span);
66              div.addEventListener(mouseover,function(){
//换成用Date对象
67 startTime = new Date().getTime(); 68 },false); 69 div.addEventListener(mouseout,function(){ 70 totalTime += new Date().getTime()-startTime; 71 //console.log(totalTime); 72 span.innerHTML = 鼠标离开后才会显示停留时长,stay:+Math.floor(totalTime/1000); 73 },false); 74 div.appendChild(span); 75 } 76 var div = document.getElementsByClassName(mod-spm); 77 timerCounter(div[0],startTime,totalTime,div[0].dataset[spmid]); 78 timerCounter(div[1],startTime,totalTime,div[1].dataset[spmid]); 79 timerCounter(div[2],startTime,totalTime,div[2].dataset[spmid]); 80 </script>

 

看它的运行结果,猛戳:区块停留计数器第二个版本

哎,貌似也可以接受,但是当我看到别人的代码的时候,心里可就不这样想了。我就是觉得自己写完了嘛,然后就去百度下看看还有没有别的方法,看别人有没有更好的实现,于是我看到了下面这段代码:

 

1     function ShowStayTime(obj) {
2         this.obj = obj;
3         this.totalTime = 0;
4         this.enterTime = null;
5         this.divTime= document.createElement(‘div‘);
6     }
7     ShowStayTime.prototype = {
8         constructor:ShowStayTime,
9         init: function() {
10             this.showStayTime();
11             this.obj.appendChild(this.divTime);
12             this.beginTime();
13             this.leaveTime();
14         },
15         showStayTime: function() {
16             var message = "";
17             message = "停留时间" + this.totalTime + "ms";
18             this.divTime.innerText = message;
19         },
20         beginTime: function() {
21             this.obj.addEventListener("mouseenter",function() {
22                 this.enterTime = new Date();
23             })
24         },
25         leaveTime: function() {
26             var temp = this;
27             this.obj.addEventListener("mouseleave",function() {
28                 temp.totalTime += new Date().getTime() - this.enterTime.getTime();
29                 temp.showStayTime();
30             })
31         }
32     }
33     var divs = document.getElementsByClassName(‘mod-spm‘);
34         var show1 = new ShowStayTime(divs[0]);
35         var show2 = new ShowStayTime(divs[1]);
36         var show3 = new ShowStayTime(divs[2]);
37         show1.init();
38         show2.init();
39         show3.init();

 

用的也是Date方法,可是人家写的代码比我的 有思想多了。值得我学习呀~~于是我也更意识到了,真的还有很长的路要走,基础不能忘,设计模式这种高端的东西也要搞起来,代码也不能总那么屎下去吧,小胡子跟我说,厉害的人写代码的境界,能用原生的js实现任何他能想到的结果...

于是我又开始看我的代码,写的封装啊什么的很好的那种,我还没有那个能力,那我的代码,我还能为你做些什么呢?然后我就开始打开浏览器各种试,到IE的时候,我就傻了,看吧,都不起作用了~~这会想不改进也不行了,那就做些力所能及的吧~~~

 

那我第一个版本的实现,问题有哪些呢?实际上:

 

1. 细心的人应该早就注意到了,IE并不支持getElementsByClassName()这个函数;

2. 事件绑定没有注意跨浏览器的问题;

3. data-*的兼容性问题!!

 

这有个data-*的兼容性情况:

 

  • Internet Explorer 11+
  • Chrome 8+
  • Firefox 6.0+
  • Opera 11.10+
  • Safari 6+

对于第一个问题:本来的做法就可以是,先使用getElementsByTagName("*")取出文档中所有元素,然后进行遍历,使用正则表达式找出匹配的元素放入一个数组返回。

可是,看了正美大神的下面这篇文章: document.getElementsByClassName()的理想实现  我觉得就想用这个方法了。而且心里无比崇拜。

第二个问题:事件绑定的跨浏览器问题,IE低版本根本不支持getElementsByClassName这个方法,哎,不能总自己小打小闹呀,养成好的习惯吧,快快改进。然后又看到正美大神的这篇文章:javascript处理时间的一些兼容写法 总结的很全面的。

第三个问题:由于data-*也存在兼容性问题,所以对于IE的低版本只能用getAttribute()方法获取。

 

然后改进改进改进:

 

 

  1 <!DOCTYPE html>
  2 <html lang="zh">
  3 <head>
  4 <meta charset=utf-8>
  5 <title>timeCounter</title>
  6 </head>
  7 
  8 <style>
  9   .mod-spm[data-spmid=‘123‘]{
 10      width: 100px;
 11      height: 100px;
 12      margin-right: auto;
 13      margin-left: auto;
 14      margin-bottom: 20px;
 15      background-color: #fff;
 16      border: 2px #000 solid;
 17   }
 18   .mod-spm[data-spmid=‘456‘]{
 19      width: 100px;
 20      height: 100px;
 21      margin-right: auto;
 22      margin-left: auto;
 23      margin-bottom: 20px;
 24      background-color: #fff;
 25      border: 2px #000 solid;
 26   }
 27   .mod-spm[data-spmid=‘789‘]{
 28      width: 100px;
 29      height: 100px;
 30      margin-right: auto;
 31      margin-left: auto;
 32      margin-bottom: 20px;
 33      background-color: #fff;
 34      border: 2px #000 solid;
 35   }
 36 </style>
 37 <body>
 38      <div class="mod-spm" data-spmid="123">
 39        <div class="child_a"></div>
 40        <div class="child_b"></div>
 41        <div class="child_c"></div>
 42        <div class="child_d"></div>
 43      </div>
 44      <div class="mod-spm" data-spmid="456">
 45        <div class="child_a"></div>
 46        <div class="child_b"></div>
 47        <div class="child_c"></div>
 48        <div class="child_d"></div>
 49      </div>
 50      <div class="mod-spm" data-spmid="789">
 51        <div class="child_a"></div>
 52        <div class="child_b"></div>
 53        <div class="child_c"></div>
 54        <div class="child_d"></div>
 55      </div>
 56     <script type="text/javascript">
 57          var counter = 0,
 58              counter1 = 0,
 59              counter2 = 0,
 60              counter3 = 0;
 61          var timer = null;
 62          function timerCounter(div,counter,num){
 63              addEvent(div,mouseover,function(){
 64                 timer = setInterval(count,1000);             
 65              }); 
 66              addEvent(div,mouseout,function(){
 67              clearInterval(timer);
 68              //这里设置null是很有必要的,为了重复计数
 69              timer = null;
 70              });
 71             var span = document.createElement(span);
 72             div.appendChild(span);
 73             function count(){
 74                 counter++;
 75                 span.innerHTML = STAY:+counter;
 76                 console.log(区块+num+上停留的时间为:+counter);
 77             } 
 78             return counter;
 79          }
 80 
 81          //跨浏览器的事件处理函数
 82          var addEvent = function( obj, type, fn ) {
 83                 if (obj.addEventListener)
 84                     obj.addEventListener( type, fn, false );
 85                 else if (obj.attachEvent) {
 86                     obj["e"+type+fn] = fn;
 87                     obj.attachEvent( "on"+type, function() {
 88                         obj["e"+type+fn]();
 89                     } );
 90                 }
 91             };
 92            
 93             //解决getElementsByClassName在低版本ie中不支持的问题
 94             var getElementsByClassName = function(searchClass,node,tag) {
 95                     if(document.getElementsByClassName){
 96                         return  document.getElementsByClassName(searchClass)
 97                     }else{    
 98                         node = node || document;
 99                         tag = tag || *;
100                         var returnElements = []
101                         var els =  (tag === "*" && node.all)? node.all : node.getElementsByTagName(tag);
102                         var i = els.length;
103                         searchClass = searchClass.replace(/\-/g, "\\-");
104                         var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
105                         while(--i >= 0){
106                             if (pattern.test(els[i].className) ) {
107                                 returnElements.push(els[i]);
108                             }
109                         }
110                         return returnElements;
111                     }
112                 }
113 
114           var div = getElementsByClassName(mod-spm);
115           var block1 = num(div[0]);
116           var block2 = num(div[1]);
117           var block3 = num(div[2]);
118           timerCounter(div[0],counter1,block1);
119           timerCounter(div[1],counter2,block2);
120           timerCounter(div[2],counter3,block3); 
121           //解决data-*的兼容性问题
122           function num(div){
123              if(div.dataset){
124                 return div.dataset[spmid];
125              }else{
126                 return div.getAttribute(data-spmid);
127              }
128            }   
129 
130     </script>
131 </body>  
132 </html>

 

这会换浏览器也不会出问题啦,各个浏览器下猛戳:跨浏览器的区块停留计时

需要源代码的同学自己去我的github上下载吧,不过记得先star我喔,不star不给下哈哈,star太少不开心。

 

一道原生js题目引发的思考(鼠标停留区块计时)

标签:style   blog   http   io   color   ar   使用   java   sp   

原文地址:http://www.cnblogs.com/skylar/p/4074433.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!