一 背景知识:

1.1 #号的作用

#代表网页中的一个位置。其右面的字符,就是该位置的标识符。
就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。
为网页位置指定标识符,有两个方法:

一是使用锚点,比如<a name="print"></a>,
二是使用id属性,比如<div id="print">。

HTTP请求不包括#.

2.2 a元素与URL对象

URL对象是浏览器的原生对象,可以用来构造、解析和编码 URL。一般情况下,通过window.URL可以拿到这个对象。

元素和元素都部署了这个接口。这就是说,
它们的 DOM 节点对象可以使用 URL 的实例属性和方法。

例如:我们利用a标签来获取一些东西

// <a href="#box1">我跳到box1</a>
// 上面时html代码
var a = document.querySelector('a');

	console.log(a.href); //返回整个 URL
	console.log(a.hash); //返回片段识别符,以井号#开头
	console.log(a.hostname); //返回域名
	console.log(a.search); //返回查询字符串,以问号?开头

二 锚点定位含义

锚点其实就是可以让页面定位到某个位置上的点。在高度较高的页面中经常见到。

// 锚点跳转有两种形式:
 
   *1. a标签 + name / href 属性
   *2. 使用标签的id属性

三 锚点定位实现

1、利用#

缺点:url会发生改变,会在url最后面加上片段识别符#box2,这样就改变了URL的路径,这是我们不想看到的.因为再次刷新的时候回出现问题.

<a href="#box1">我跳到box1</a>
	<a href="#" name="#box2">我跳到box2</a>

	<div id="box1"></div>
	<div id="box2"></div>

2、scrollTop.offset

1、这种方法url不会发生改变,阻止了a标签的默认行为.所以a标签不会跳转.
2、 document.querySelector(target).offsetTop;
$(target).offset().top 都是去求出盒子参照body定位对应的top值,这是因为offet家族的定义是:
如果元素自身是非固定定位,并且所有的父元素都没有定位,那么他的定位父级是body .
3、 上面代码的target得到格式都是#box1,此时在原生中利用属性选择器来获取元素要很多.

document.querySelector(target) 等价于
document.querySelector('#box1')
<script>
	var aList = document.querySelectorAll('a');
	//给每一个a标签注册点击事件
	for( var i=0;i < aList.length;i++){
		aList[i].addEventListener('click', function(e){

			//阻止a标签的默认行为
			e = e || window.event;
			e.preventDefault();

			//获取整个href路径
			//var target = this.href;
			//获取#片段识别符
			var target = this.hash;

			//获取box参照于body定位的top值
			var offsetTop = document.querySelector(target).offsetTop;
			//将页面跳转到对应的位置
			document.documentElement.scrollTop = offsetTop;	
		});
	}
</script>

3、srollIntoView

含义

scrollIntoView 是 HTMLElement 集合下的一个 API,每一个 HTML 元素都拥有这个 API。它的作用就和字面意思一样:滚动到可视区。

Element 接口的 scrollIntoView()方法会滚动元素的父容器,使被调用 scrollIntoView()的元素对用户可见。

语法

语法:

element.scrollIntoView(); // 等同于 element.scrollIntoView(true)
element.scrollIntoView(alignToTop); // Boolean 型参数
element.scrollIntoView(scrollIntoViewOptions); // Object 型参数

参数解释:

alignToTop:它是一个 Boolean 值,它用来规定元素出现在可视区后与可视区的对齐方式,为 true 代表顶端对齐,false 代表低端对齐。
scrollIntoViewOptions:它是一个对象,该参数主要是配置元素的动画效果以及位置的,它有一下 3 个属性:
behavior:它定义元素出现在可视区内过程的动画,有 auto 和 smooth 两种选择。
block:定义元素的垂直方向的对齐方式,有"start", “center”, “end”, 或 “nearest” 4 个选项,默认 start。
inline:定义元素水平对齐方式,有"start", “center”, “end”, 或 “nearest"4 个选项,默认"nearest”。

有些小伙伴可能发现两个参数都能定义元素的对齐方式,它们之间有什么联系呢?当 alignToTop 为 true 时,scrollIntoViewOptions: {block: “start”, inline: “nearest”}这是它的默认值,当 alignToTop 为 false 时,scrollIntoViewOptions: {block: “end”, inline: “nearest”}这是它的默认值。

<body>
  <div class="box">
    <div class="left">
      <p>第一段内容</p>
      <p>第二段内容</p>
      <p>第三段内容</p>
    </div>
    <div class="right">
      <div class="content">
        我是第一段内容
      </div>
      <div class="content">
        我是第二段内容
      </div>
      <div class="content">
        我是第三段内容
      </div>
    </div>
  </div>
</body>
<script>
  // 获取三个标题元素
  let pDomList = document.getElementsByTagName('p');
  // 获取三段内容元素
  let contentDomList = document.getElementsByClassName('content');


  // 添加点击事件
  for (let index = 0; index < pDomList.length; index++) {
    pDomList[index].addEventListener('click', () => {
      contentDomList[index].scrollIntoView({
        behavior: 'smooth',
        block: 'start',
        inline: 'start'
      })
    })
  }
</script>
<style>
  * {
    margin: 0;
    padding: 0;
  }


  .box {
    width: 100vw;
    height: 100vh;
    display: flex;
    overflow: hidden;
  }


  .left {
    width: 300px;
    height: 100%;
    border-right: 2px solid green;
  }


  p {
    height: 40px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border: 1px solid #ccc;
  }


  .right {
    flex: 1;
    overflow: auto;
  }


  .content {
    width: 100%;
    height: 1000px;
    border-top: 1px solid yellow;
    padding: 20px;
    box-sizing: border-box;
  }
</style>