• 作者:老汪软件技巧
  • 发表时间:2024-08-18 11:03
  • 浏览量:

需求

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

效果

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

实现1. 准备DOM 结构

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

核心代码就是

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

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

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方法 讲解:

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

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

参数

目前我们实现了效果.

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

效果:

总结

整体下来的思路就是:

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