案例:电梯导航功能

实现功能:

1. 点击左边的小li,会滚动到右边对应的内容区(电梯导航 -> 内容区)

① 当滚动到某一位置时,就让电梯导航显示出来

② 点击电梯导航页面可以滚动到相应内容区域

③ 核心算法:因为电梯导航模块和内容区模块是一一对应的,所以对应的索引号是一样的

④ 当点击电梯导航某个小模块时,就可以拿到当前小模块的索引号

⑤ 就可以把animate要移动的距离求出来:当前索引号内容区模块它的offset().top

⑥ 然后执行动画即可

2. 当滚动到右边的内容区,作边的小li会添加相应的类(内容区 -> 电梯导航)

① 当点击电梯导航的某个小li,当前小li添加current类,兄弟移除类名

② 当页面滚动到内容区域某个模块,左侧电梯导航相对应的小li模块,也会添加current类,兄弟移除current类

③ 触发的事件是页面滚动,因此这个功能要写到页面滚动事件里面

④ 需要用到each遍历内容区域大模块。each里面能拿到内容区域每一个模块元素和索引号

⑤ 判断的条件:被卷去的头部 >= 内容区域里面每个模块的offset().top

⑥ 就利用这个索引号找到相应的电梯导航小li,添加current类

一个bug:当我们刷新页面的时候并不能显示电梯导航,这是因为我们写的代码只允许页面滚动的时候,并且滚动到一定的位置才能显示电梯导航

解决办法:将显示和隐藏电梯导航的功能封装到一个函数里去,在页面加载的时候调用一次,页面滚动的时候再调用一次

另一个bug:此时如果点击电梯导航的某一个小li时,会出现重新把其他的小li样式背景选择一遍之后才到被点击的小li上。而我们想要的效果是,点击某个小li后,直接去往被点击的小li那添加样式,而不需要它多次选择其他的小li,出现类似抖动的情况

为什么会出现这个问题呢?这是因为我们的代码中写的是,当我们点击某个小li之后,会使我们的页面滚动起来,而在滚动的过程中,会触发给当前内容区对应的小li增加样式的事件。

如何解决呢?当我们点击了小li,此时不需要执行页面滚动事件里面的小 li 的背景选择。

我们可以使用节流阀的方法,也叫互斥锁,增加一个flag判断条件,判断是点击事件还是滚动事件,如果是点击事件,就上一个锁,不要执行滚动事件里面的代码,点击事件完成之后再释放锁。

    <!-- 楼层区 start -->
    <div class="floor">
        <!-- floor不需要给高度,里面的楼层盒子撑开就行了 -->
        <!-- 一楼家电模块 -->
        <div class="jiadian w">
            家用电器模块
        </div>
        <!-- 二楼手机模块 -->
        <div class="shouji w">
            手机通讯模块
        </div>
        <!-- 三楼电脑模块 -->
        <div class="diannao w">
            电脑办公模块
        </div>
        <!-- 四楼家具模块 -->
        <div class="jiaju w">
            精品家具模块
        <!-- 之后的楼层都接在后面叠加,布局直接采用上面的样式布局,不需要做大的修改 -->
    </div>
    <!-- 楼层区 end -->

    <!-- 固定电梯导航 start -->
    <div class="fixedtool">
        <ul>
            <li class="current">家用电器</li>
            <li>手机通讯</li>
            <li>电脑办公</li>
            <li>家具家居</li>
        </ul>
    </div>
    <!-- 固定电梯导航 end -->
// JS逻辑代码
$(function() {
    // 当我们点击了小li,此时不需要执行页面滚动事件里面的小 li 的背景选择。
    // 使用节流阀的方法,设置一个flag标识
    var flag = true;
    // 1. 显示隐藏电梯导航
    // 直到滚动条滚动到今日推荐的部分,就显示电梯导航
    var toolTop = $(".recommend").offset().top;
    toggleTool();
    // 显示和隐藏电梯导航的功能,在页面加载的时候调用一次
    function toggleTool() {
        if ($(document).scrollTop() >= toolTop) {
            $(".fixedtool").fadeIn();
        } else {
            $(".fixedtool").fadeOut();
        }
    }
    // 在页面滚动的时候再调用一次
    $(window).scroll(function() {
        toggleTool();
        // 3. 页面滚动到某个内容区域,左侧电梯导航小li相应添加和删除current类名
        if (flag) {
            $(".floor .w").each(function(i, ele) {
                if ($(document).scrollTop() >= $(ele).offset().top) {
                    // console.log(i);  i表示当前内容区的索引号
                    $('.fixedtool li').eq(i).addClass('current').siblings().removeClass('current');
                }
            });
        }        
    });
    // 2. 点击电梯导航页面可以滚动到相应的内容区域
    $('.fixedtool li').click(function() {
        flag = false;
        // console.log($(this).index());
        // 点击之后让当前的小li添加背景颜色,兄弟元素清除样式
        $(this).addClass('current');
        $(this).siblings().removeClass('current');
        // 当每次点击小li,就需要计算出页面要去往的位置
        // 选出对应索引号的内容区的盒子,计算它的.offset().top
        var current = $(".floor .w").eq($(this).index()).offset().top;
        // 页面动画滚动效果
        $("body, html").stop().animate({
            scrollTop: current
        }, function() {
            // 当点击小li,执行页面滚动动画完成之后,打开节流阀
            flag = true;
        });
    });
})
原文地址:https://www.cnblogs.com/zcy9838/p/13022453.html