vue 实现导航锚点联动

<!--
 * @Author: ex-jinming002
-->
<script>
import jQuery from 'jquery'
export default {
  data() {
    return {
      allMenuList: [
        { id: 1, name: '导航', children: [] },
        { id: 2, name: '导航1' },
        { id: 3, name: '导航2' },
        { id: 4, name: '导航3' },
      ],
      activeMenu: 0,
    }
  },
  created() {},
  mounted() {
    const that = this
    // 获取滚动dom元素
    this.scrollBox = document.getElementById('scrollBox')
    const jump = jQuery('.do-jump')
    console.log(jump)
    const topArr = []
    for (let i = 0; i < jump.length; i++) {
      topArr.push(jump.eq(i).position().top)
    }
    // 监听dom元素的scroll事件
    this.scrollBox.addEventListener(
      'scroll',
      () => {
        const current_offset_top = that.scrollBox.scrollTop
        for (let i = 0; i < topArr.length; i++) {
          if (current_offset_top <= topArr[i]) {
            // 根据滚动距离判断应该滚动到第几个导航的位置
            that.activeMenu = i
            break
          }
        }
      },
      true,
    )
  },
  methods: {
    // 跳转
    jump(index) {
      this.activeMenu = index // 当前导航
      const jump = jQuery('.do-jump').eq(index)
      const scrollTop = jump.position().top + this.scrollBox.scrollTop // 获取需要滚动的距离
      // Chrome
      this.scrollBox.scrollTo({
        top: scrollTop,
        behavior: 'smooth', // 平滑滚动
      })
    },
  },
}
</script>

<template>
  <div class="NavScroll">
    <div class="all-title">
      全部应用
      <p class="fr">
        <span
          v-for="(item, index) in allMenuList"
          :key="item.id"
          :class="[index === activeMenu ? 'active' : '']"
          @click="jump(index)"
          >{{ item.name }}</span
        >
      </p>
    </div>
    <div  class="applications-content">
      <div v-for="val in allMenuList" :key="val.id" class="all-list do-jump">
        <p class="applications-title">{{ val.name }}</p>
        <ul class="applications-list">
          <li
            v-for="item in val.children"
            :key="item.id"
            class="applications-item"
            @click="changeRouterForRight(item.pathName, item.menuCode)"
          >
            <img src="" />
            <span>{{ item.name }}</span>
            <template v-if="showEdit">
              <i
                v-if="addOrRemove(item.menuCode) == 0"
                class="el-icon-circle-plus add-btn"
                @click="addMenu(item.menuCode)"
              />
              <i
                v-if="addOrRemove(item.menuCode) == 1"
                class="el-icon-remove remove-btn"
                @click="removeMenu(item.menuCode)"
              />
            </template>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<style scoped >
.NavScroll {
  width: 800px;
  margin: 20px auto;
  .all-title {
    height: 45px;
    line-height: 45px;
    background-color: red;
    .fr {
      float: right;
      margin: 0 30px;
      > span {
        float: left;
        text-align: center;
        margin-left: 20px;
        cursor: pointer;
      }
      .active {
        &::after {
          content: '';
          display: block;
          height: 0;
          border-bottom: 1px solid black;
        }
      }
    }
  }
  .applications-content {
    width: 100%;
    height: 300px;
    overflow: hidden;
    overflow-y: scroll;
    .all-list {
      height: 200px;
      margin: 10px 0;
      // background-color: blue;
      border: 1px solid #ccc;
    }
  }
}
</style>