在下面的代码中,我将检查窗口是否正在滚动过某个点,如果是,更改元素使用固定位置,以便它不滚动页面的顶部。唯一的问题是,似乎是HIGHLY客户端内存密集型(并真正陷入了滚动速度),因为在每一个滚动像素我一遍又一遍更新元素的样式属性。
将检查attr是否已经在那里,然后尝试更新它有显着的区别?是否有完全不同的和更有效的做法得到相同的结果?
$(window).scroll(function () { var headerBottom = 165; var fcHeight = $("#pnlMainNavContainer").height(); var ScrollTop = $(window).scrollTop(); if (ScrollTop > headerBottom) { $("#HeaderContentBuffer").attr("style","margin-top:" + (fcHeight) + "px;"); $("#AddFieldsContainer").attr("style","position:fixed;width:320px;top:70px;left:41px;"); } else { $("#HeaderContentBuffer").attr("style","margin-top: 0px;"); $("#AddFieldsContainer").removeAttr("style"); } });
在我键入这个,我注意到StackOverflow.com使用相同类型的功能,其黄色的“类似问题”和“帮助”菜单在此页的右手边。我不知道他们是如何做到的。
解决方法
可以使用的一种技术是在滚动事件上设置定时器,并且仅当滚动位置在短时间内没有改变时才执行主要工作。我使用该技术调整大小事件有相同的问题。你可以试验什么超时值似乎工作正确。在滚动期间更短的时间更新具有更短的暂停,并且因此可能在滚动期间更频繁地运行,更长的时间需要用户实际暂停所有运动达有意义的时间。你将不得不尝试什么超时值最适合您的目的,它最好是在一个相对较慢的计算机上测试,因为这是滚动滞后的问题将最显着的地方。
这里是一个大致的想法如何可以实现:
var scrollTimer = null; $(window).scroll(function () { if (scrollTimer) { clearTimeout(scrollTimer); // clear any prevIoUs pending timer } scrollTimer = setTimeout(handleScroll,500); // set new timer }); function handleScroll() { scrollTimer = null; var headerBottom = 165; var fcHeight = $("#pnlMainNavContainer").height(); var ScrollTop = $(window).scrollTop(); if (ScrollTop > headerBottom) { $("#HeaderContentBuffer").attr("style","margin-top: 0px;"); $("#AddFieldsContainer").removeAttr("style"); } }
您也可以通过在滚动第一次启动时缓存一些选择器来加快滚动功能,因此不必每次都重新计算。这是一个地方,每次创建一个jQuery对象的额外开销可能不会帮助你。
这里有一个jQuery add-on方法来处理滚动计时器:
(function($) { var uniqueCntr = 0; $.fn.scrolled = function (waitTime,fn) { if (typeof waitTime === "function") { fn = waitTime; waitTime = 500; } var tag = "scrollTimer" + uniqueCntr++; this.scroll(function () { var self = $(this); var timer = self.data(tag); if (timer) { clearTimeout(timer); } timer = setTimeout(function () { self.removeData(tag); fn.call(self[0]); },waitTime); self.data(tag,timer); }); } })(jQuery);
工作演示:http://jsfiddle.net/jfriend00/KHeZY/
然后你的代码将实现如下:
$(window).scrolled(function() { var headerBottom = 165; var fcHeight = $("#pnlMainNavContainer").height(); var ScrollTop = $(window).scrollTop(); if (ScrollTop > headerBottom) { $("#HeaderContentBuffer").attr("style","margin-top: 0px;"); $("#AddFieldsContainer").removeAttr("style"); } });