js implementation of the scalable menu seen on imooc today: http://www.imooc.com/video/93
When I practice, I find that this code is problematic. Error code first
<ul> <li style="background-color: red; width: 100px">First</li> <li style="background-color: red; width: 100px">The second</li> <li style="background-color: red; width: 100px">Third</li> </ul> <script type="text/javascript"> window.onload = function () { var ls = document.getElementsByTagName("li"); for (var i = 0; i < ls.length; i++) { ls[i].onmouseover = function () { var This = this; This.time = setInterval(function () { This.style.width = This.offsetWidth + 20 + "px"; if(This.offsetWidth >= 160){ This.style.width = 160 + "px"; clearInterval(This.time); } }, 30) };} for (var i = 0; i < ls.length; i++) { ls[i].onmouseout = function () { var This = this; This.time= setInterval(function () { This.style.width = This.offsetWidth - 20 + "px"; if(This.offsetWidth <=100) { This.style.width = 100 + "px"; clearInterval(This.time); } }, 30) }; } } </script>
This code ignores two issues.
1. If the mouse hovers away in an instant and goes to the blank (that is, when the length does not increase much), a few more times, it may cause an infinite cycle.
Reasons: When leaving, the action of levitation lengthening is not finished, while levitation, the action of levitation reduction is not finished, conflicts occur, and animation cycle will occur when the cycle conditions are met at some time.
2. What happens if the mouse hovers away and goes to another list and tries several times? We can also see the occurrence of infinite loop animation.
The reason classifies add and subtract animations into the obj.time attribute. If you press 2 to operation, it is very likely that at some time the same obj will increase or decrease to conflict, which should have been reduced, but the action of increase will continue to increase, leading to the reduction can not be completed.
Solution: 1 - ----"Clear all animations that the mouse leaves at the beginning of the mouse hover function, and all animations that the mouse hovers at the beginning of the mouse hover function.
2 - ----"Mouse hovering and leaving should be separated, not the same attribute, and should be expressed by two attributes respectively. (Finally, I will talk about why attributes should be used, not global variables, not local variables, but also why v a r T his= this)
The correct code is as follows:
<script type="text/javascript"> window.onload = function () { var ls = document.getElementsByTagName("li"); for (var i = 0; i < ls.length; i++) { ls[i].onmouseover = function () { //Internal function 1 var This = this; clearInterval(This.off); This.on = setInterval(function () { This.style.width = This.offsetWidth + 20 + "px"; if(This.offsetWidth >= 160){ This.style.width = 160 + "px"; clearInterval(This.on); } }, 30) };} for (var i = 0; i < ls.length; i++) { ls[i].onmouseout = function () { //Internal function 2 var This = this; clearInterval(This.on) This.off = setInterval(function () { This.style.width = This.offsetWidth - 20 + "px"; if(This.offsetWidth <=100) { This.style.width = 100 + "px"; clearInterval(This.off); } }, 30) }; } } </script>
Why use attributes?
First of all, we must not use local variables, internal function 2 (1) must not be able to access local variables of internal function 1 (2), then there is no way to clear the animation in the "animation stack".
Why not use global variables o n, o f. Let's consider a case. Suppose I move quickly from listA to listB. At this point on represents an increased animation off represents a reduced animation
The moment from A to B, B triggers onmouseover to perform clearInterval(off) A was forced to stop before it could be reduced to its original length.
In other words, if you use global variables from then on, the animation does not distinguish which object the animation is directed at.
Why use var This = this?
Setinterval is a delay function. At the time of execution, this has become Windows and we want this to be bound to the address of all variables on the list, This, to store lIst, because the object that performs var This = this.this binding has not changed yet.