• 通过链接如何找到指定位置


    通过链接如何找到指定位置

    现在有一个需求,就是通过链接调到指定页面的位置,不然就得不同链接不同页面,那样工作量大之外,还太浪费。于是决定在一个页面中,通过链接跳到指定位置。需要跟github的效果一样

    github

    通过上面的github图,可以看出几个基本需求

    • 跳转时携带id,自动跳转到指定位置
    • 被选中的元素具有 focus 效果
    • 被选中的元素具体顶部有一段距离
    • 点击 document 时,清除选中效果,同时路由上删除id
    • 点击浏览器回退按钮,可以出现新进入时的效果

    开启挖掘之旅

    鉴于上面的需求,通过hash(锚点)是可以简单实现上面的要求,个人当然希望能用浏览器及css解决的,就尽量解决,若是不行只能通过js来尽可能模拟出想要的效果。

    在此,我们需要恶补2个知识点

    地址栏改变,页面不刷新不滚动 介绍

    通过github的效果,我们知道地址栏是改变了,但是视觉上确实没有感到有任何一样(除了focus效果消失)。

    通过historyreplaceState便可以实现上述效果

    // 记录第一次的值
    const firstTop = document.scrollingElement.scrollTop
    // 清空hash
    window.location.hash = ""
    // 地址栏刷新不跳转
    window.history.replaceState(null, null, window.location.pathname + window.location.search)
    // 再回滚之前的位置
    document.scrollingElement.scrollTop = firstTop
    

    github的代码 github

    鄙人的代码没有那么全面,但是原理是一样的

    至此页面刷新不跳转便算完成了

    利用hash进行定位

    利用锚点进行定位

    html

    <a href="./base.html#two" class="header">two</a>
    
    > base.html
    
    <div class="wide segment" id="two">
      <h2>two</h2>
      <div class="sc">
        <div class="ui placeholder fluid active inverted">
          <div class="image header">
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
          </div>
        </div>
      </div>
    </div>
    

    css

    .wide {
      padding: 20px;
      border: 1px solid #333;
    }
    
    .wide .sc {
      padding: 20px;
      border: 1px solid transparent;
    }
    
    .wide:target .sc {
      border: 1px solid red;
      box-shadow: 0 0 0 .2em pink;
    }
    

    js

     // 链接改变页面不刷新
    const changeUrl = () => {
      const firstTop = document.scrollingElement.scrollTop
      window.location.hash = ""
      window.history.replaceState(null, null, window.location.pathname + window.location.search)
      document.scrollingElement.scrollTop = firstTop
    }
    /**
      * @description: 若是通过链接进入当前页面,最好使用 `one`
      * 如此事件只执行一次即可
      */
    $(document).on('click', function () {
      changeUrl()
    })
    

    效果图
    hash

    通过上面的方式,便可以完成基本需求,但是有几点需要探讨一下

    • 定位的盒子无法设置距离顶部多高,完全由锚点说的算了
    • 如果携带了?v=1类似参数,锚点便完全失效了

    针对上面遗留的问题,使用js进行改版

    鉴于使用js,那就需要完全按上面的需求,进行js定制化,需要一个一个完成方可。

    • 滚动到指定位置
    • 选中效果
    • 浏览器回退时需要恢复focus效果
    • 携带参数依旧有锚点效果

    code开启

    html

    <a href="./update.html#one" class="header">one</a>
    // 携带参数
    <a href="./update.html#two?v=1" class="header">two?v=1</a>
    
    > update.html
    <div class="wide " id="one">
      <h2>one</h2>
      <div class="sc">
        <div class="ui placeholder fluid">
          <div class="image header">
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
          </div>
        </div>
      </div>
    </div>
    <div class="wide " id="two">
      <h2>two</h2>
      <div class="sc">
        <div class="ui placeholder fluid">
          <div class="image header">
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
            <div class="line"></div>
          </div>
        </div>
      </div>
    </div>
    

    css

    .wide .sc {
      padding: 20px;
      border: 1px solid transparent;
    }
    .wide.target .sc,
    .wide:target .sc {
      border: 1px solid red;
      box-shadow: 0 0 0 .2em pink;
    }
    

    js

    /**
      * @description: 通过url获取对应元素
      * @return: node
      */
    const getEl = () => {
      const urlId = location.href.split('#')[1]
      if (!urlId) return null
      return document.getElementById(urlId.replace(/?.*/, ''))
    }
    /**
      * @description: 初始进入页面跳转到指定位置,同时生成focus效果
      */
    const elScroll = () => {
      const el = getEl()
      if (!el) return
      $(el).addClass('target')
      // 此处用来获取需要滚动的位置
      const scrollY = el.getBoundingClientRect().top + document.scrollingElement.scrollTop - 40
      $(document.scrollingElement).scrollTop(scrollY)
    }
    /**
      * @description: 监听地址栏hash值变化
      */
    const listenHashChange = () => {
      window.addEventListener('hashchange', () => {
        elScroll()
      }, false)
    }
    /**
      * @description: 地址栏改变页面不刷新
      */
    const changeUrl = () => {
      // 移除选中效果
      getEl() && $(getEl()).removeClass('target')
      const firstTop = document.scrollingElement.scrollTop
      window.location.hash = ""
      window.history.replaceState(null, null, window.location.pathname + window.location.search)
      document.scrollingElement.scrollTop = firstTop
    }
    

    效果图

    • 不携带参数
      no-has-params

    • 携带参数
      has-params

    至此,基本完成想要的需求

    效果页面链接

    总结

    • 项目地址link

    • 谷歌浏览器会记住默认位置 link,但使用了该方法

      if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
      }
      

      会与原始锚点方案有冲突

    • 滚动到指定位置,可以通过scrollIntoView来实现,只是依旧跟锚点存在同样的问题,无法设置距离顶部的位置

    • 对于获取scrollTop=0值的想法,可以通过getBoundingClientRect来进行处理

    不足之处

    • 使用js方案,前后的滚动可以看出来,而是用锚点模式较好,若是不考虑设置距离顶部的高度,个人更加偏向于两者进行处理(通过是否携带参数来进行判断)

    参考链接

  • 相关阅读:
    回调函数
    BIRT实现组内跨行计算
    POJ 3616 Milking Time DP题解
    string的内存管理问题
    天津政府应急系统之GIS一张图(arcgis api for flex)解说(三)显示地图坐标系模块
    myeclipse将java项目转换成web项目,导出war包
    Spring之IOC篇章具体解释
    为RAC私有网络配置网卡Bonding
    聊聊高并发(九)实现几种自旋锁(四)
    鼠标放上去Div旋转特效代码
  • 原文地址:https://www.cnblogs.com/sinosaurus/p/11812990.html
Copyright © 2020-2023  润新知