需求
这次的需求就是,在页面中存在一个滚动的数据列表,点击某个按钮的时候或者其他类似操作,可以定位到具体的列表项,并且出现在可视范围内;
方案1:scrollIntoView()
第一种方案利用Element.scrollIntoView()
函数;
Element
接口的 scrollIntoView() 方法会滚动元素的父容器,使被调用 scrollIntoView() 的元素对用户可见。
直接调用这个scrollIntoView()的话,默认是元素的顶端和其所在滚动区的可视区域的顶端对齐;
先贴一下我的代码结构:
index.tsx:
import { useEffect, useState } from 'react'
import './index.less'
const ScrollIntoView = () => {
const listData = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T'
]
const [target, setTarget] = useState('H')
const scrollTo = (index: string) => {
const curEl = document.getElementById(index)
curEl?.scrollIntoView()
}
useEffect(() => {
scrollTo(target)
}, [target])
return (
<div className="scroll-wrapper">
<h2>ScrollIntoView: 滚动到可视区域</h2>
<div className="list-box">
{listData.map((item) => (
<div
className={['list-item', target === item ? 'active' : ''].join(' ')}
key={item}
id={item}
onClick={() => {
setTarget(item)
}}
>
{item}
</div>
))}
</div>
<div className="btns-box">
scrollTo:
<div
className="btn"
onClick={() => {
setTarget('A')
}}
>
A
</div>
<div
className="btn"
onClick={() => {
setTarget('E')
}}
>
E
</div>
<div
className="btn"
onClick={() => {
setTarget('H')
}}
>
H
</div>
</div>
</div>
)
}
export default ScrollIntoView
滚动效果:
这种效果不好的地方在于:我们点击的元素本来就在可视范围内,他也会滚动到父元素的顶端;
方案2:scrollIntoView(scrollIntoViewOptions)
scrollIntoView
函数还可以传递参数来制定他的滚动行为,具体参照MDN的官方文档;
我这里就演示一种:
curEl?.scrollIntoView({
block: 'nearest',
inline: 'nearest',
behavior: 'smooth'
})
滚动效果:
这种效果是不是就比较舒服了,在火狐和Safari浏览器也试过了,效果是一致的;
方案3:scrollIntoViewIfNeeded(谨慎使用)
这种方案是谨慎使用的,因为它是非标准特性:
**
Element.scrollIntoViewIfNeeded()
**方法用来将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域。如果该元素已经在浏览器窗口的可见区域内,则不会发生滚动。此方法是标准的Element.scrollIntoView()方法的专有变体。
curEl?.scrollIntoViewIfNeeded()
但是这种方式,可能项目编译都通不过,你们可以试试;
方案4: 第三方库scroll-into-view-if-needed
安装下这个库:
npm i scroll-into-view-if-needed
npm的文档:scroll-into-view-if-needed;
效果网站各种滚动效果
我这里简单用了一下:
// 引入第三方库
import scrollIntoView from 'scroll-into-view-if-needed'
if (curEl) {
scrollIntoView(curEl, {
behavior: 'smooth',
block: 'nearest'
})
}
其实这个的效果跟方案2很像;
这是几种比较类似且简单的效果,如果你对滚动的距离啊位置啊有更高的要求,可以自己根据元素的位置信息,自己进行计算;
以上就是关于元素滚动到可视区域的分享了;自己比较推荐方案2!!☺️