详解scrollTo和scrollIntoView的区别

1,715 阅读7分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第2天,点击查看活动详情

在实现元素滚动相关需求上,官方给我们提供了四个方法:scroll(), scrollBy(), scrollIntoView()和scrollTo()。这四种方式其实在使用上是有一定的场景的,在某些时候是可以互相替代的。

Element.scroll()

scroll()是用来在给定的元素中滚动到某个特定坐标的Element 接口,通俗地讲就是滚动到具体坐标的位置上。

scroll()有两种使用形式:坐标形式和options形式。

坐标形式

element.scroll(x-coord, y-coord)
  • x-coord: 指在元素左上方区域横轴方向上想要显示的像素
  • y-coord: 指在元素左上方区域纵轴方向上想要显示的像素

实例

<template>
  <div class="hello">
    <div id="targetEle">我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素</div>
    <p>
      <button @click="scroll">滚动元素</button>
    </p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
    }
  },
  methods: {
    scroll () {
      let ele = document.querySelector('#targetEle')
      ele.scroll(50, 50)
    }
  }
}
</script>
<style scoped>
#targetEle {
  width: 200px;
  height: 100px;
  padding: 20px;
  overflow: auto;
}
</style>

初始效果:

企业微信截图_55ae9a01-02e9-4b53-9d55-5ed8b8d92981.png

滚动后效果:滚动过程还有平滑滚动的过渡。

企业微信截图_04c7fca1-ce89-4ddc-b3f2-66f961ce3bae.png

options形式

element.scroll(options)

这里的options指的是通用的选项条件ScrollToOptions,这篇文章介绍的scroll,scrollBy和scrollTo方法里面的options都是指这个。里面包含如下选项:

  • top: 指在元素左上方区域纵轴方向上的像素
  • left:指在元素左上方区域横轴方向上的像素
  • behavior: 定义动画过渡效果,属性值有'auto'或'smooth'。默认为'auto'。

实例

scroll () {
  let ele = document.querySelector('#targetEle')
  ele.scroll({
    top: 100,
    left: 100,
    behavior: 'smooth'
  })
}

初始化效果:

同上

滚动后效果:

企业微信截图_f2fba5e7-b907-4a0d-ab68-020dd43bf9aa.png

适用场景

从上面的实例效果来看:

  1. Element必须是可以滚动的元素
  2. 滚动的时候是按照Element来计算坐标的,里面的padding会被忽略

Element.scroll()适用于已知要滚动的位置在容器中的坐标, 这个坐标表示的位置是绝对位置。

Element.scrollBy()

scrollBy() 方法是使得元素滚动一段特定距离的 Element 接口,通俗地将就是滚动到距离元素特定的距离的位置上。

scroll()也有两种使用形式:坐标形式和options形式。

坐标形式

element.scrollBy(x-coord, y-coord);
  • x-coord: 指元素要在横轴上滚动的距离
  • y-coord: 指元素要在纵轴上滚动的距离

实例

<template>
  <div class="hello">
    <div id="targetEle">我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素</div>
    <p>
      <button @click="scroll">滚动元素</button>
    </p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
    }
  },
  methods: {
    scroll () {
      let ele = document.querySelector('#targetEle')
      ele.scroll(100, 50)
    }
  }
}
</script>
<style scoped>
#targetEle {
  width: 400px;
  height: 100px;
  padding: 20px;
  margin: 10px;
  overflow: auto;
}
</style>

初始化效果:

企业微信截图_4bd27e53-4cdd-42d7-8fb6-d76edb98574f.png 滚动后效果:

企业微信截图_ad15eec0-1609-4998-b12b-d8d7b0ba3e4f.png

options形式

element.scrollBy(options)

这里的options指的是通用的选项条件ScrollToOptions, 同上。

实例

scroll () {
  let ele = document.querySelector('#targetEle')
  ele.scrollBy({
    top: 50,
    left: 100,
    behavior: 'smooth'
  })
}

效果同上

适用场景

从上面的实例效果来看:

  1. Element必须是可以滚动的元素
  2. 滚动的时候是按照Element来计算距离的,里面的padding会被忽略

Element.scrollBy()适用于从当前位置滚动到某个相对位置,从当前位置起向右和向下滚动多少像素。

Element.scrollIntoView()

滚动元素的父容器,直到元素在用户可见的视口内,通俗讲就是将元素滚动到浏览器的可视窗口内。

Element.scrollIntoView()里面的参数一共有三种形式:

  • 不传
  • 布尔型参数
  • 对象型参数

不传参数

element.scrollIntoView()

不传参数的话等同于element.scrollIntoView(true),表示元素的顶端将和其所在滚动区的可视区域的顶端对齐

实例

<template>
  <div class="hello">
    <div id="targetEle">
      <div>我是顶部元素</div>
      <div class="main-box">我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素我是可以滚动的目标元素</div>
    </div>
    <p>
      <button @click="scroll">滚动元素</button>
    </p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
    }
  },
  methods: {
    scroll () {
      let ele = document.querySelector('.main-box')
      ele.scrollIntoView()
    }
  }
}
</script>
<style scoped>
#targetEle {
  width: 400px;
  height: 100px;
  padding: 20px;
  margin: 10px;
  overflow: auto;
}
</style>

初始化效果:

企业微信截图_1538ed31-e120-487a-afc7-8069cfa2a0e5.png

滚动后效果:

企业微信截图_21294fb7-57a9-448a-ad72-e412e97b6f76.png

传布尔型参数

element.scrollIntoView(alignToTop)

其中alignToTop可以取下面几种值:

  • true: 表示元素的顶端将和其所在滚动区的可视区域的顶端对齐。相当于scrollIntoViewOptions: {block: "start", inline: "nearest"}
  • false: 表示元素的底端将和其所在滚动区的可视区域的底端对齐。相当于scrollIntoViewOptions: {block: "end", inline: "nearest"}

实例 为true的情况我们已经了解了,这里我们以false为例

scroll () {
  let ele = document.querySelector('.main-box')
  ele.scrollIntoView(false)
}

初始化效果:

同上

滚动后效果:

企业微信截图_18448bd6-c737-4ddf-8a40-444a6e157f7e.png

传对象型参数

element.scrollIntoView(scrollIntoViewOptions)

其中scrollIntoViewOptions包括以下属性:

  • behavior: 定义动画过渡效果,属性值有'auto'或'smooth'。默认为'auto'。
  • block:定义垂直方向的对齐,属性值有'start', 'end', 'center'或者'nearest'。默认为'start'。
  • inline:定义水平方向的对齐,属性值有'start', 'end', 'center'或者'nearest'。默认为'nearest'。

实例

scroll () {
  let ele = document.querySelector('.main-box')
  ele.scrollIntoView({
    behavior: 'smooth',
    block: 'nearest'
  })
}

效果同上

适用场景

  1. Element必须是可以滚动的元素
  2. 滚动的时候是相对于容器的视口来对齐的

适用于没有覆盖层的情况,需要将某元素显示在视口的顶部或者底部。比如:消息对话框

不适用的场景

场景1:如果在容器中存在其他的位于改元素上层的元素(比如absolute或者fixed定位的其他元素),那么当前元素滑动上去就会被遮挡。 原因:scrollIntoView是相对视口来定位的,只能设置对齐方式,而不能设置具体的位置

企业微信截图_a6371fd1-22cd-4e64-b05d-72af685d1b91.png

场景2:如果当前滚动容器存在水平和垂直的滚动条,那么实际上并不能保证没有设置的那个方向是不动的。 原因:scrollIntoView设置出现在容器中时,如果存在滚动条的时候,是会自动调整位置,没办法具体到像素的位置进行定位。这种时候是不适合使用scrollIntoView的。

企业微信截图_8300920a-28a3-4194-99e0-1e95b4f13326.png

Element.scrollTo()

Element 的 scrollTo() 方法可以使界面滚动到给定元素的指定坐标位置。

scrollTo方法也有两种,坐标形式和options选项

坐标形式

element.scrollTo(x-coord, y-coord)
  • x-coord: 指期望滚动到位置水平轴上距元素左上角的像素
  • y-coord: 指期望滚动到位置竖直轴上距元素左上角的像素

options形式

element.scrollTo(options)

这里的options指的是通用的选项条件ScrollToOptions, 同上上。

scrollTo的用法和scroll基本一致,这里我就不展开描述了。

scrollTo和scrollIntoView的区别

  • scrollTo适用于将元素滑动到任意具体的位置,可以精确到像素,而scrollIntoView只能将元素滚动到视口的顶部和底部。
  • scrollIntoView在某些场景下会有一些问题(见当前文档scrollIntoView部分),而scrollTo可以精准控制滑动。

scrollTo, scroll和scrollBy的区别

scrollTo和scroll类似,滚动的时候都是绝对位置,scrollBy是相对位置,每次滚动都是相对上一个元素的位置进行滚动的。