zoukankan      html  css  js  c++  java
  • 那些年原生js实现的楼层跳转

      最近做一个需求~~楼层跳转(京东、淘宝侧边导航),由于现在项目都用框架,所以 jquery是不能再用了,只好自己原生写一个,其实实现起来很简单,无非就是获取到每个楼层距离文档顶部的距离,然后通过控制滚动条来实现,麻烦的是需求在变,由于突然引出了一个锚点导航遇到了fixed,所以只好重新思考,满足需求。

      简单的楼层跳转样例可以先看一下之前写的demo(https://lewiscutey.github.io/yintai),看起来效果很好吧,下面详解其中的坑:

    1.锚点导航遇到fixed

      现在布局一般都要box-sizing:border-box/content-box,所以不要再用padding-top:50px;margin-top:-50px;这种写法了,最好直接写一个子元素来定位,这样既不占空间,又可以精确定位,下面是简易的demo:

    .floor {
        position: relative;
        #anchor{
            position: absolute;
            top: -56px;
            width: 100%;
        }
    }

    2.子元素永远比父元素层级z-index高

      大家总是习以为常的拿z-index来决定层级,当有时候就算z-index:9999!important;还是不起作用的时候,也许就是父子元素定位出了问题,这样唯一的解决办法就是给他们在加一个父元素,原来的父子元素现在变成了兄弟方可有效,呜呜,不幸中招。

    3.慎用getBoundingClientRect()

      大家可能对这个方法有点陌生,其实就是用来获取dom节点对于bom的相对位置,今天要说的这个坑是当页面中有锚点链接时,直接路由进来的页面会显示到锚点的内容区域,从而通过getBoundingClientRect()获取到的值就会乱套,因此如果用作楼层跳转里楼层高度获取值时,就会失效了,所以慎用这个获取相对位置的方法,我们一般用offsetTop来获取dom节点对于bom的相对位置,这就要求把该dom直接作为body的子元素,经检测方便可靠,下面是一个简单的demo:

    let flag = true;
    let floorHeights = [];
    let slideBar = document.querySelector("#slide-bar");
    let floors = document.querySelectorAll(".floor");
    let floorLinks = document.querySelectorAll("#slide-bar .floor-link");
    for (let i = 0; i < floors.length; i++){
        floorHeights.push(floors[i].offsetTop - 56);
    }
    window.onscroll = function() {
        let scrollTop = document.body.scrollTop||document.documentElement.scrollTop;
        if(scrollTop > 750){
            if(flag){
                flag = false;
                slideBar.style.bottom = '50%';
            }
        }else{
            if(!flag){
                flag = true;
                slideBar.style.bottom = '-200%';
            }
        }
        for (let i = 0; i < floorHeights.length; i++) {
            if(floorHeights[i] < scrollTop + 200){
                for (let j = 0; j < floorHeights.length; j++) {
                    floorLinks[j].style.opacity = 0;
                }
                floorLinks[i].style.opacity = 1;
            }
        }     
    }
    window.onscroll();
    for (let i = 0; i < floorLinks.length; i++) {
        floorLinks[i].index = i;
        floorLinks[i].onmouseover = function(){
            for (let j = 0; j < floorLinks.length; j++) {
                floorLinks[j].style.opacity = 0;
            }
            this.style.opacity = 1;
        }
    
        floorLinks[i].onclick = function() {
            for (let j = 0; j < floorLinks.length-1; j++) {
                floorLinks[j].style.opacity = 0;
            }
            document.body.scrollTop = floorHeights[this.index];
            document.documentElement.scrollTop = floorHeights[this.index];
        }
    
        floorLinks[floorLinks.length-1].onclick = function() {
            document.body.scrollTop = 0;
            document.documentElement.scrollTop = 0;
        }
    }

       哈哈,命名即思维,我相信通过代码大家可以弄的一清二楚,下面附上经典老图(一图胜千言)!

      以后要把这些琐碎的知识点记录下来,就如阮一峰老师所说的:炫耀从来不是我的动机,好奇才是,一边学习,一边记录!

  • 相关阅读:
    初学Python,对于开发工具不是很了解?一文带你选择适合你的开发工具
    Python文学家为Python写的一首词?(附中英文版)
    大数据到底怎么学: 数据科学概论与大数据学习误区
    Python写代码的时候为什么要注释?Sun因此被Oracle收购
    大数据分析:大数据时代如何发现身边的大数据?
    大数据经典学习路线(及供参考)之 一
    关于如何获取移动端 touchmove 事件中真正触摸点下方的元素
    webservice
    VS文件后缀名大全详解
    string 转 char* (C#)
  • 原文地址:https://www.cnblogs.com/lewiscutey/p/7780970.html
Copyright © 2011-2022 走看看