页面需求:
- 点击左侧版本号,右侧展示对应版本内容并置于顶部
- 右侧某一内容滚动到顶部时,左侧需要展示高亮
实现效果:

实现代码:
<template><div><div class="historyBox pd-20 bg-white"><div class="w100 flex h100" v-if="versionList.length > 0"><div class="left size-14"><divv-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"><divv-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);},checkItemsAtTop() {const rightBox = document.querySelector(".right");const rightItems = Array.from(rightBox.querySelectorAll(".rightItem"));rightItems.forEach((item, index) => {const rect = item.getBoundingClientRect();const containerRect = rightBox.getBoundingClientRect();if (rect.top - containerRect.top <= 0 &&rect.bottom - containerRect.top >= 0) {this.scrollIndex = index;}if (this.scrollStopTimer) {clearTimeout(this.scrollStopTimer);}this.scrollStopTimer = setTimeout(this.onScrollStopped, 150); });},onScrollStopped() {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;leftBox.scrollTo({top: offsetTop,behavior: "smooth", });},gotoTarget(index) {this.clickIndex = index;this.activeIndex = index;const rightItems = document.querySelectorAll(".rightItem");const rightBox = document.querySelector(".right");const targetRightItem = rightItems[index];const offsetTop = targetRightItem.offsetTop - rightBox.offsetTop + 1;rightBox.scrollTo({top: offsetTop,behavior: "smooth", });},getList() {listAllVersion().then((response) => {this.versionList = 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>