注册
web

排行榜--实现点击视图自动滚动到当前用户所在位置.

需求


我们今天来实现一下,点击当前用户的div, 自动滚动到用户在排行榜中的位置.


效果


大家可以先看一下下面的GIF, 所实现的效果.


QQ2024817-122950.gif


实现


1. 准备DOM 结构


首先,我们在进行列表建设的时候, 需要准备好一个数据. 因为此处我们是使用的vue3来进行编写. 对于列表我们使用的是v-for列表渲染来做的. 在渲染的时候, 我们需要给每一个列表项(当前就是每一个用户项)添加一个自定义属性. 具体的话, 可以看下 下方的关键代码.


image.png


核心代码就是


 <div v-for="(item, index) in rankingData" :key="item.user.id" :data-key="item.user.id"
</div>



因为数据是后端返回的, 是包含的user_id,而且这个user_id 是不可能重复的. 我们只要保证每个列表的自定义的属性是唯一的即可.



image.png


2. 绑定方法,实现方法


接下来,我们需要考虑的是,在点击的时候,如何获取到当前的dom. 这对我们目前来说就很容易了, 因为我们可以根据据user_id 拿到我们当前点击的dom.


添加一个方法


<!-- 当前用户排名情况 -->
<div class="text-white w-[100%] ...." @click="scrollToCurrentRankingPosition(userId)">

实现方法.


第一步: 拿到rankingList的dom实例.


这里我们通过vue3提供ref拿到dom. 可以看下
模板引用


<div v-else class=" overflow-auto bg-white" ref="rankingList">

const rankingList = ref(null);

第二步: 根据userId获取到具体的DOM


const currentItem = rankingList.value.querySelector(`[data-key="${id}"]`);

第三步: 使用scrollIntoView方法滚动视图到当前选中的元素


 // 平滑滚动到当前元素
currentItem.scrollIntoView({ behavior: 'smooth', block: 'center' });

scrollIntoView方法 讲解:



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

简单来讲就是被调用的者的元素出现在用户的视线里面.
scrollIntoView() 方法有三种调用形式:



  1. scrollIntoView():无参数调用,元素将滚动到可视区域顶部,如果它是第一个可见元素。
  2. scrollIntoView(alignToTop):接受一个布尔值参数,决定元素是与滚动区的顶部还是底部对齐。
  3. scrollIntoView(scrollIntoViewOptions):接受一个对象作为参数,提供了更多的滚动选项。

参数



  • alignToTop(可选):布尔值,控制元素滚动到顶部还是底部对齐。默认为 true(顶部对齐)。
  • scrollIntoViewOptions(可选实验性):对象,包含以下属性:

    • behavior:定义滚动行为是平滑动画还是立即发生。可取值有 smooth(平滑动画)、instant(立即发生)或 auto(由CSS的 scroll-behavior 属性决定)。
    • block:定义垂直方向的对齐方式,可取值有 startcenterend 或 nearest。默认为 start
    • inline:定义水平方向的对齐方式,可取值有 startcenterend 或 nearest。默认为 nearest



目前我们实现了效果.


QQ2024817-13328.gif


但是我们发现,还可以继续改进, 目前我们虽然滚动到了屏幕的中间, 但是我们很难去发现. 所以我们可以继续完善一下这个方法. 就是滚动到视图的中间的同时高亮选中的DOM.


3. 额外扩展, 高亮当前的元素


定义一个两个方法,一个用于应用样式, 一个应用于移除样式.


const applyHighlightStyles = (element) => {
element.style.transition = 'background-color 1s ease, border-color 1s ease';
element.style.border = '1px solid transparent'; // 预定义边框样式
element.style.borderColor = '#006cfe'; // 设置边框颜色
element.style.backgroundColor = '#cfe5ff'; // 设置背景色为浅蓝色
};

const removeHighlightStyles = (element) => {
element.style.backgroundColor = ''; // 移除背景色
element.style.borderColor = 'transparent'; // 移除边框颜色
};

然后再在我们之前的方法的后面加入代码


            // 设置高亮显示的样式
applyHighlightStyles(currentItem);

// 清除之前的定时器(如果有)
if (currentItem._highlightTimer) {
clearTimeout(currentItem._highlightTimer);
}

// 设置定时器,2秒后移除高亮显示
currentItem._highlightTimer = setTimeout(() => {
removeHighlightStyles(currentItem);
currentItem._highlightTimer = null;
}, 2000);


然后在组件卸载前记得清除定时器.


onUnmounted(() => {
if (rankingList.value) {
// 遍历所有项目,清除定时器
rankingList.value.querySelectorAll('[data-key]').forEach(item => {
if (item._highlightTimer) {
clearTimeout(item._highlightTimer);
item._highlightTimer = null;
}
});
}
});

效果:
image.png


总结


整体下来的思路就是:



  1. v-for的时候, 给每个循环的元素添加一个自定义的属性.(value:user_id), 不重复且能标识每个元素.
  2. 点击之后,拿到id,透传给方法,然后通过id获取到当前的元素.
  3. 使用Element.scrollIntoView(), 将当前的选中的DOM自动滚动视图的中间.
  4. 高亮显示当前的元素之后(2s)进行取消高亮.

作者:心安事随
来源:juejin.cn/post/7403576996393910308

0 个评论

要回复文章请先登录注册