当前位置: 首页 > article >正文

vue实现根据点击或滑动展示对应高亮

页面需求:

  • 点击左侧版本号,右侧展示对应版本内容并置于顶部
  • 右侧某一内容滚动到顶部时,左侧需要展示高亮

实现效果:

请添加图片描述

实现代码:

<template>
  <div>
    <div class="historyBox pd-20 bg-white">
      <div class="w100 flex h100" v-if="versionList.length > 0">
        <div class="left size-14">
          <div
            v-for="(item, index) in versionList"
            :key="index"
            class="leftItem pd-10 pointer"
            :class="index == activeIndex ? 'isActive' : ''"
            @click="gotoTarget(index)"
          >
            <div>{{ item.versionNumber }}</div>
            <div>{{ item.releaseTime }}</div>
          </div>
        </div>
        <div class="right">
          <div
            v-for="(item, index) in versionList"
            :key="index"
            class="rightItem pd-20 center"
            :class="index == activeIndex ? 'isActive' : ''"
          >
            <div v-html="item.versionDescription" class="ql-editor w60"></div>
          </div>
        </div>
      </div>
      <div class="w100 h100 center size-16 gray-2" v-else>暂无版本记录</div>
    </div>
  </div>
</template>

<script>
import { listAllVersion } from "./components/api";

export default {
  name: "VersionHistory",
  data() {
    return {
      versionList: [], // 表格数据
      activeIndex: 0, // 高亮下标
      clickIndex: 0, // 点击下标
      scrollIndex: 0, // 滚动下标
      scrollStopTimer: null,
    };
  },
  created() {
    this.getList();
  },
  mounted() {},
  methods: {
    // 监听鼠标移入元素 、右侧父元素滚动
    checkItemsHover() {
      const rightBox = document.querySelector(".right");

      // 监听父容器的滚动事件
      rightBox.addEventListener("scroll", this.checkItemsAtTop);

      // 页面加载时也检查一次
      window.addEventListener("load", this.checkItemsAtTop);
    },
    // 监听元素 rightItem 触顶
    checkItemsAtTop() {
      const rightBox = document.querySelector(".right");
      const rightItems = Array.from(rightBox.querySelectorAll(".rightItem"));
      rightItems.forEach((item, index) => {
        // 使用 getBoundingClientRect 来获取元素相对于视口的位置
        const rect = item.getBoundingClientRect();
        const containerRect = rightBox.getBoundingClientRect();

        // 判断元素是否触顶父容器
        if (
          rect.top - containerRect.top <= 0 &&
          rect.bottom - containerRect.top >= 0
        ) {
          this.scrollIndex = index;
          // this.activeIndex = index;
        }

        // 清除之前的定时器,防止重复触发
        if (this.scrollStopTimer) {
          clearTimeout(this.scrollStopTimer);
        }
        // 设置新的定时器,在滚动停止后延迟指定时间触发
        this.scrollStopTimer = setTimeout(this.onScrollStopped, 150); // 150ms 的延迟可以根据需要调整
      });
    },
    // 滚动停止后的回调函数
    onScrollStopped() {
      // console.log("滚动停止了", this.scrollIndex, this.clickIndex);
      // 在这里放置你希望在滚动停止后执行的代码
      if (this.scrollIndex < this.clickIndex) {
        this.activeIndex = this.clickIndex;
        this.clickIndex = 0;
      } else {
        this.activeIndex = this.scrollIndex;
      }
      const leftItems = document.querySelectorAll(".leftItem");
      const leftBox = document.querySelector(".left");
      const targetLeftItem = leftItems[this.activeIndex];
      // 计算目标元素距离父容器顶部的距离
      const offsetTop = targetLeftItem.offsetTop - leftBox.offsetTop;

      // 使用 scrollTo 方法让父容器滚动到目标元素的位置
      leftBox.scrollTo({
        top: offsetTop,
        behavior: "smooth", // 如果需要平滑滚动,请确保父容器设置了 scroll-behavior: smooth;
      });
    },
    // 定义当鼠标移入时触发的函数
    gotoTarget(index) {
      // this.scrollIndex = index;
      this.clickIndex = index;
      this.activeIndex = index;

      const rightItems = document.querySelectorAll(".rightItem");
      const rightBox = document.querySelector(".right");
      const targetRightItem = rightItems[index];
      /* // 使用 scrollIntoView 方法让目标元素滚动到视图顶部
      targetRightItem.scrollIntoView({ behavior: "smooth", block: "start" }); */

      // 计算目标元素距离父容器顶部的距离
      const offsetTop = targetRightItem.offsetTop - rightBox.offsetTop + 1;

      // 使用 scrollTo 方法让父容器滚动到目标元素的位置
      rightBox.scrollTo({
        top: offsetTop,
        behavior: "smooth", // 如果需要平滑滚动,请确保父容器设置了 scroll-behavior: smooth;
      });
    },
    /** 查询列表 */
    getList() {
      listAllVersion().then((response) => {
        this.versionList = response.data;
        // .concat(response.data)
        // .concat(response.data)
        // .concat(response.data)
        // .concat(response.data);
        this.$nextTick(() => {
          this.checkItemsHover();
        });
      });
    },
  },
};
</script>
<style lang="scss" scoped>
@import "./components/quill.snow.css";
.historyBox {
  height: calc(100vh - 90px);
  ::-webkit-scrollbar {
    width: 6px;
    // height: 24px;
  }

  /* 滚动槽的样式设置 */
  ::-webkit-scrollbar-track {
    background: #eee;
  }

  /* 滚动条滑块的样式设置 */
  ::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.1);
    background: rgb(158, 203, 255);
    border-radius: 12px;

    &:hover {
      background: rgb(95, 169, 253);
    }
  }
  .left {
    width: 260px;
    min-width: 260px;
    height: 100%;
    // height: calc(100vh - 117px);
    overflow-y: auto;

    .leftItem {
      display: flex;
      justify-content: space-evenly;
      align-items: center;
      border: 1px solid #eee;
    }
    .isActive {
      border: 1px solid #3f8cff;
      border-left: 4px solid #3f8cff;
      color: #3f8cff;
      background: rgba(63, 140, 255, 0.1);
      font-weight: bold;
    }
  }
  .right {
    box-sizing: border-box;
    width: calc(100% - 260px);
    height: 100%;
    // height: calc(100vh - 117px);
    overflow-y: auto;
    background: #eef6ff;

    .rightItem {
      border: 1px dotted #eef6ff;
      &:hover {
        border: 1px dotted #ddd;
      }
      .w60 {
        width: 60%;
      }
    }
    .isActive {
      // border: 1px dotted #ddd;
      border: 1px dotted #3f8cff;
      // box-shadow: 0px 0px 20px #3f8cff;
      // box-shadow: 0px 5.04px 10.08px rgba(55, 114, 233, 0.22),
      //   inset 0px 5.04px 10.08px rgba(211, 221, 242, 1);
    }
  }
}
</style>

http://www.kler.cn/a/565394.html

相关文章:

  • Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景
  • 基于EasyExcel封装的Excel工具类,支持高效导出和读取操作
  • Qt for Android下QMessageBox背景黑色、文字点击闪烁
  • JSX 实现列表渲染
  • react绑定ref调用
  • 转化率(漏斗分析)——mysql计算过程
  • Amazon Neptune深度解析:高性能图形分析和无服务器数据库的场景化实践与技术优
  • XFeat:轻量级的深度学习图像特征匹配
  • 机器学习数学基础:34.二列相关教程
  • Redis 面试
  • 矩阵的 正定(Positive Definite)与负定(Negative Definite):从Fisher信息矩阵看“曲率”的秘密
  • smolagents学习笔记系列(十)Examples - Web Browser Automation with Agents
  • Linux设备驱动开发-Pinctrl子系统使用详解
  • 导入 Excel 规则批量修改或删除 Word 内容
  • 【Linux】进程间通信——命名管道
  • Python解决“比赛配对”问题
  • 爱普生SG-8101CE可编程晶振赋能智能手机的精准心脏
  • Redis 源码分析-内部数据结构 SDS
  • 在VSCode中使用MarsCode AI最新版本详解
  • 12. 三昧真火焚环劫 - 环形链表检测(快慢指针)