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

2024-08-18 16:10:16 浏览数 (1)

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

效果

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

QQ2024817-122950.gifQQ2024817-122950.gif

实现

1. 准备DOM 结构

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

image.pngimage.png

核心代码就是

代码语言:javascript复制
 <div v-for="(item, index) in rankingData" :key="item.user.id" :data-key="item.user.id"
 </div>

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

image.pngimage.png

2. 绑定方法,实现方法

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

添加一个方法

代码语言:javascript复制
<!-- 当前用户排名情况 -->
        <div class="text-white w-[100%] ...."  @click="scrollToCurrentRankingPosition(userId)">

实现方法.

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

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

代码语言:javascript复制
<div v-else class=" overflow-auto bg-white" ref="rankingList">

const rankingList = ref(null);

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

代码语言:javascript复制
const currentItem = rankingList.value.querySelector(`[data-key="${id}"]`);

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

代码语言:javascript复制
 // 平滑滚动到当前元素
  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:定义垂直方向的对齐方式,可取值有 startcenterendnearest。默认为 start
    • inline:定义水平方向的对齐方式,可取值有 startcenterendnearest。默认为 nearest

目前我们实现了效果.

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

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

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

代码语言:javascript复制
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'; // 移除边框颜色
};

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

代码语言:javascript复制
            // 设置高亮显示的样式
            applyHighlightStyles(currentItem);

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

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

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

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

效果:

image.pngimage.png

总结

整体下来的思路就是:

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

0 人点赞