处理$(窗口)的更有效方法。jquery中的滚动函数?

处理$(窗口)的更有效方法。jquery中的滚动函数?,jquery,scroll,Jquery,Scroll,在下面的代码中,我检查窗口是否滚动超过某个点,如果是,则将元素更改为使用固定位置,以便它不会滚动到页面顶部。唯一的问题是,它似乎是高度客户端内存密集型的(并且确实阻碍了滚动速度),因为在每一个滚动像素上,我都在不断更新元素上的样式属性 在尝试更新attr之前,检查attr是否已经存在,是否会产生重大影响?是否有一种完全不同且更有效的做法来获得相同的结果 $(window).scroll(function () { var headerBottom = 165; var fcHei

在下面的代码中,我检查窗口是否滚动超过某个点,如果是,则将元素更改为使用固定位置,以便它不会滚动到页面顶部。唯一的问题是,它似乎是高度客户端内存密集型的(并且确实阻碍了滚动速度),因为在每一个滚动像素上,我都在不断更新元素上的样式属性

在尝试更新attr之前,检查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:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
    } else {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
    }
}
您还可以通过在滚动第一次启动时缓存一些选择器来加速滚动功能,这样就不必每次都重新计算它们。在这种情况下,每次创建jQuery对象的额外开销可能对您没有帮助


下面是一个jQuery附加方法,可为您处理滚动计时器:

(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);
工作演示:

然后,您的代码将按如下方式实现:

$(window).scrolled(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");
    }
});

我发现这种方法对于
$(window.scroll()

查看此主题

一个更有效的解决方案是设置一个更长的时间间隔来检测您是否
靠近页面底部或顶部。这样,您甚至不必使用
$(window).scroll()

来提高函数的效率

在删除/添加样式之前,只需检查样式属性是否存在

$(window).scroll(function () {
    var headerBottom = 165;
    var fcHeight = $("#pnlMainNavContainer").height();

    var ScrollTop = $(window).scrollTop();
    if (ScrollTop > headerBottom) {
        if (!$("#AddFieldsContainer").attr("style")) {
            $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
            $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
        }
    } else {
        if ($("#AddFieldsContainer").attr("style")) {
            $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
            $("#AddFieldsContainer").removeAttr("style");
        }
    }
});

在这里设定一些逻辑。实际上,您需要将ATT设置为一次开启,一次关闭。因此:

var checker = true;
$(window).scroll(function () {

    .......

    if (ScrollTop > headerBottom && checker == true) {
        $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
        checker == false;
    } else if (ScrollTop < headerBottom && checker == false) {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
        checker == true;
    }   
});
var checker=true;
$(窗口)。滚动(函数(){
.......
如果(ScrollTop>headerBottom&&checker==true){
$(“#HeaderContentBuffer”).attr(“样式”,“边距顶部:+(fcHeight)+“px;”);
$(“#AddFieldsContainer”).attr(“样式”,“位置:固定;宽度:320px;顶部:70px;左侧:41px;”;
checker==假;
}else if(ScrollTop
以下答案不使用jQuery,而是使用现代浏览器功能实现相同的结果。OP还询问是否有其他更有效的方法。下面的方法比jQuery甚至是使用
onScroll
事件侦听器的普通JavaScript解决方案的性能要好得多

我们将使用两件大事的组合:

  • position:sticky'
    CSS属性
  • IntersectionObserver
    API
为了达到
标题
卡住的效果,我们可以使用
位置的惊人组合:sticky;顶部:0pxCSS属性。这将允许元素与页面一起滚动,并在到达页面顶部时卡住(好像它是
固定的

要更改固定元素或任何其他元素的样式,我们可以使用-来观察两个元素相交处的更改

为了达到我们想要的效果,我们将添加一个
sentinel
元素,当
header
元素到达顶部时,它将作为一个指示器。换言之:

  • 当哨兵未与视口相交时,我们的
    标题位于顶部
  • 当哨兵与视口相交时,我们的
    标题不在顶部
有了这两个条件,我们可以将任何必要的样式应用于
标题
或其他元素

const sentinelEl=document.getElementById('sentinel'))
const headerell=document.getElementById('header'))
const stuckClass=“卡滞”
常量处理程序=(条目)=>{
if(头鱼){
如果(!条目的[0]。isIntersecting){
headerre.classList.add(stuckClass)
}否则{
headerre.classList.remove(stuckClass)
}
}
}
const observer=新窗口。IntersectionObserver(处理程序)
观察者观察(哨兵)
html,
身体{
字体系列:Arial;
填充:0;
保证金:0;
}
.topContent,
.网页内容,
#标题{
填充:10px;
}
#标题{
位置:粘性;
顶部:0px;
过渡:所有0.2s线性;
}
#头。卡住了{
背景色:红色;
颜色:白色;
}
.topContent{
高度:50px;
背景颜色:灰色;
}
.网页内容{
高度:600px;
背景颜色:浅灰色;
}

内容高于我们的粘性元素
粘头
这一页的其余部分

@Hengjie-当计时器触发时不重置
scrollTimer
,可能会导致您稍后对不再活动的计时器对象调用
clearTimeout()
。您不应该这样做,因此设置为
null
更为正确,这样我们就知道计时器不再处于活动状态,将来也不会对其调用
clearTimeout()
。也许浏览器是保护的
var checker = true;
$(window).scroll(function () {

    .......

    if (ScrollTop > headerBottom && checker == true) {
        $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
        checker == false;
    } else if (ScrollTop < headerBottom && checker == false) {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
        checker == true;
    }   
});