vue3自定义动态锚点列表,实现本页面锚点跳转效果

需求:当前页面存在多个模块且内容很长时,需要提供一个锚点列表,可以快速查看对应模块内容

实现步骤:

1.每个模块添加唯一id,添加锚点列表div

<template>
  <!-- 模块A -->
  <div id="modalA">
    <ModalA/>
  </div>
  <!-- 模块B -->
  <div id="modalB">
    <ModalB/>
  </div>
  
  <!-- 动态锚点 -->
    <div class="anchor-box">
      <ul>
        <li v-for="(item, index) in status.anchors" :key="index" :class="{'active': status.anchorActive===index}" @click="onAnchor(item, index)">
          <i class="spot"></i>
          <span>{{ item.title }}</span>
        </li>
      </ul>
    </div>
</template>

2.初始化锚点列表,监听滚动事件

<script lang='ts' setup>
import { debounce } from "lodash-es";

const status:any = reactive({
  anchors: [], // 动态锚点集合
  anchorActive: -1, // 锚点高亮
});

onMounted(() => {
  init()
});

const init = () => {
  initAnchors()
  // 这里的content-wrap是设置overflow-y:auto的div,如果滚动条是全局的可以改成window,即:window.addEventListener('scroll',  handleScroll)
  scrollDom.value = document.querySelector('.content-wrap')
  scrollDom.value.addEventListener('scroll',  handleScroll)
}

// 设置动态锚点集合
const initAnchors = () => {
  status.anchors = [
    {
      title: "模块A",
      id: "modalA"
    },
    {
      title: "模块B",
      id: "modalB"
    },
  ]
}

// 监听滚动
const handleScroll = () => {
  let scrollPosition = scrollDom.value.scrollTop
  status.anchors.forEach((v, index) => {
    let dom = document.getElementById(`${v.id}`)
    const offsetTop = dom.offsetTop  
    const offsetHeight = dom.offsetHeight
    if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) {
      status.anchorActive = index
    }
  })
}

// 锚点跳转
const onAnchor = (item, index) => {
  // 移除scroll事件
  scrollDom.value.removeEventListener('scroll', handleScroll)
  status.anchorActive = index

  nextTick(() => {
    const target = document.getElementById(item.id);
    target?.scrollIntoView({
      behavior: 'smooth',
      block: 'start',     // 垂直对齐方式(start/center/end)
      inline: 'nearest'   // 水平对齐方式
    });

    // 重新绑定scroll事件
    addScrollEvent()
  })
}

// 绑定scroll事件
const addScrollEvent = debounce(() => {
  scrollDom.value.addEventListener('scroll', handleScroll)
}, 1500)
</script>

3.设置锚点样式


  .anchor-box {
    position: fixed;
    top: 100px;
    right: 50px;
    width: 120px;
    height: calc(100vh - 80px - 40px);
    overflow-y: auto;
    &::-webkit-scrollbar {
      width: 0;
    }
    ul {
      position: relative;
      list-style: none;
      padding: 4px;
      box-sizing: border-box;
      background-color: rgba(240, 242, 245, 0.8);
      &:before {
        position: absolute;
        top: 0;
        left: 7px;
        width: 2px;
        height: 100%;
        background-color: #dbdada;
        content: " ";
      }
      li {
        position: relative;
        width: 100%;
        display: flex;
        margin-bottom: 6px;
        cursor: pointer;
        &.active {
          .spot {
            display: block;
          }
          > span {
            color: #1890ff;
          }
        }
        .spot {
          display: none;
          position: absolute;
          top: 6px;
          width: 8px;
          height: 8px;
          background-color: #fff;
          border: 2px solid #1890ff;
          border-radius: 50%;
          transition: top .3sease-in-out;
        }
        > span {
          width: 100%;
          line-height: 1.5;
          padding-left: 16px;
          box-sizing: border-box;
          font-size: 13px;
        }
      }
    }
  }

最终效果:

### Vue3 实现页面跳转Vue3实现页面跳转,可以利用 `scrollIntoView` 方法来完成平滑滚动的效果。通过监听用户的击事件,在方法中获取目标元素并调用该方法即可。 以下是具体的实现方式: #### HTML 结构 定义一个触发跳转的按钮以及目标区域。 ```html <div> <button @click="goAnchor(&#39;#target&#39;)">跳转</button> <!-- 页面其他内容 --> <div style="height: 100vh;"></div> <!-- 目标 --> <div id="target">这里是目标</div> </div> ``` #### JavaScript 方法 在组件的 `methods` 部分编写处理逻辑,使用 `document.querySelector` 获取目标元素,并调用其 `scrollIntoView` 方法[^4]。 ```javascript export default { name: &#39;App&#39;, methods: { goAnchor(selector) { const targetElement = document.querySelector(selector); if (targetElement) { targetElement.scrollIntoView({ behavior: &#39;smooth&#39;, // 平滑滚动效果 block: &#39;start&#39; // 对齐顶部 }); } } } } ``` 此代码片段实现了当用户击按钮时,页面会以平滑的方式滚动至指定的目标位置。 --- ### 跨页面跳转 如果需要实现在不同的路由页面之间进行跳转,则可以在导航完成后手动设置滚动行为。这通常涉及 Vue Router 的钩子函数配合 `this.$nextTick()` 来确保 DOM 已经更新后再执行操作[^3]。 假设我们有如下场景:从 `/pageA` 跳转到 `/pageB#section2`。 #### 路由配置 确保 URL 支持哈希模式或者历史模式下的传递。 ```javascript const routes = [ { path: &#39;/pageB&#39;, component: PageB }, ]; ``` #### 组件内部处理 在目标页面加载完毕后读取 URL 哈希值,并找到对应的元素。 ```javascript <template> <div> <h2>Page B Content</h2> <div id="section1">Section One</div> <div id="section2">Section Two</div> </div> </template> <script> export default { mounted() { this.scrollToHash(); }, updated() { this.scrollToHash(); }, watch: { &#39;$route.hash&#39;: function () { this.scrollToHash(); } }, methods: { scrollToHash() { this.$nextTick(() => { const hash = window.location.hash; if (hash) { const element = document.querySelector(hash); if (element) { element.scrollIntoView({ behavior: &#39;smooth&#39;, block: &#39;start&#39; }); } } }); } } }; </script> ``` 上述代码会在每次路由变化或组件重新渲染时自动检测是否有匹配的,并将其滚动到视图中心。 --- ### 总结 无论是单页还是多页应用环境下的跳转需求,都可以借助原生 DOM API 和 Vue 生命周期管理工具共同达成理想体验。对于更复杂的业务逻辑还可以考虑封装成通用服务供项目复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清岚_lxn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值