1. 需求
最近公司业务遇到了一个需求,就是页面中的方格可以拖动并调整大小,数字实时改变,本来是让我加宽高实时显示的这样一个小功能,但是确遇到了坑爹的情况。
2. 发现问题
我发现里面的盒子 点击次数越多,拖动的操作越多,就越是卡,最后就像死机了一样,非常的卡顿。
我察觉到这可能是因为事件触发过多引起的,于是我吧监听鼠标的事件console.log
了一下。发现除了事件触发的多之外,还有一点匪夷所思,我多次点击拖动操作之后,我再次点击一下盒子,竟然触发了十几次的mousedown
事件。
3. 分析问题
这个原本是要点击一次 触发一次的事件,竟然点击一次触发了十几次。
1. 需求实现思路
原本,外面盒子的mousemove
事件的监听,用于改变鼠标样式,用于改变鼠标在小盒子上的移动、左上、右上、左下、右下样式的改变。于是我觉得他不需要触发的非常频繁,于是我加上了节流函数,限制他的触发次数。
// 节流函数,限制事件短时间内触发次数
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
};
};
xxx.mousemove(throttle(function(){...},100));
限制住了外层的mousemove
测试了一下,并没有解决卡顿的问题,但是事件触发的频率确实降低了。
里面的思路是这样的。我在外层的事件点击下去的的时候,开始监听里面的小盒子的鼠标事件,于是我把小盒子的鼠标事件嵌套在了外层的mousedown
事件里面,即
bigBox.mousedown(function(){
smallBox.mousedown(functon(){...});
smallBox.mousemove(functon(){...});
})
类似这样的,我console.log
的时候发现所有的事件,都是越点越多,越点越多,就跟我平时写的bug一样,mmp,怎么就不跟我头发一样呢。
于是我查询了jquery
中的事件监听,发现他本身的监听事件,是累加触发的,比如
// 别人博客偷的
$("#btn").click(function(){alert("1");})
$("#btn").click(function(){alert("2");})
你就会打印出1和2, 后者不会覆盖前者,而是多有事件都叠加在一起触发,这也就是为什么我点击一次触发好多次,越点击越多的罪魁祸首。那知道了根源,就好办了,来人,拖出去砍了!
于是在监听生效之前,先解绑一次事件,就可以解决这个问题
如
$("#btn").unbind("click").click(function(){alert("2");});
$("#btn").unbind("click").bind("click",function(){alert("2");});
$("#btn").off("click").click(function(){alert("2");});
$("#btn").off("click").on("click",function(){alert("2");});
这样 再配合之前的节流函数,节流mousemove
事件的触发频率,就可以完美解决卡顿的问题了,因为一般视觉效果60帧比较流畅,所以时间最好设置为16ms以下,这样一秒至少触发60次,就会看起来比较流畅了。哦对了,偷的博客链接