菜单与内容联动——vue3实现

需求

使用vue3实现一个常见的二级联动功能:
点击菜单能跳转到对应位置、滚动位置应激活相应菜单

如果需不要联动,只需要点击跳转,可以通过 id<a> 标签实现
<a href="#A">A</a>
<div id="A"/>

实现

思路:
页面加载完毕后,计算各区域位置
点击菜单跳转:跳转至对应区域位置
滚动位置监听:监听可滚动的父元素,计算当前位置对应的区域,激活菜单

如果区域内容动态更新,高度不定,可在动态更新后重新计算各区域位置
手动调用父元素的 scrollTo 方法,可更精确得设置滚动位置、滚动效果
滚动触发过于频繁,可使用节流函数降低触发频率

在线演示

<script setup>
  import { ref, onMounted, onBeforeUnmount } from 'vue'
  // 菜单、区域
  const links = ref([
    { label: 'Home', id: 'home', top: 0, active: true },
    { label: 'Platform', id: 'platform', top: 0 },
    { label: 'Career', id: 'career', top: 0 },
    { label: 'Contact', id: 'contact', top: 0 },
    { label: 'About', id: 'about', top: 0 }
  ])
  // 滚动父元素
  const scrollWrap = ref()
  onMounted(() => {
    // 各区域位置计算
    links.value.forEach(s => {
      s.top = document.getElementById(s.id).offsetTop
    })
    console.log(links.value)
    // 监听 scroll 事件
    scrollWrap.value?.addEventListener('scroll', scrollThrottleHandler)
  })

  onBeforeUnmount(() => {
    // 移除 scroll 监听
    scrollWrap.value?.removeEventListener('scroll', scrollThrottleHandler)
  })

// 滚动处理
const scrollHandler = (e) => {
  let scrollTop = e.target.scrollTop, // 当前滚动位置
      idx = 0 // 当前滚动位置对应的区域下标
  for(let len = links.value.length, i = len - 1; i >= 0; i--) {
    if(scrollTop >= links.value[i].top - 63 - 2) {
      idx = i
      break
    } else {
      continue
    }
  }
  const oldIdx = links.value.findIndex(s => s.active)
  if(idx !== oldIdx) {
    links.value[oldIdx].active = false
    links.value[idx].active = true
  }
}
// 节流函数
function throttle(fn, threshhold = 250, _this) {
  let last
  let timer
  return function () {
    let context = _this
    let args = arguments
    let now = +new Date()
    if (last && now < last + threshhold) {
      clearTimeout(timer)
      timer = setTimeout(function () {
        last = now
        context ? fn.apply(context, args) : fn(...args)
      }, threshhold)
    } else {
      last = now
      context ? fn.apply(context, args) : fn(...args)
    }
  }
}
// 节流处理
const scrollThrottleHandler = throttle(scrollHandler, 300)

// 滚动到指定区域
function scrollToSection(top) {
  scrollWrap.value?.scrollTo({
    top: top - 63,
    left: 0,
    behavior: 'smooth'
  })
}
</script>

<template>
  <div class="nav">
    <span
      :class="['menu-item', { active: !!link.active }]"
      v-for="link in links"
      :key="link.label"
      v-html="link.label"
      @click="scrollToSection(link.top)"
    />
  </div>
  <div class="scroll-wrap" ref="scrollWrap">
    <div class="scroll-view">
      <div
        class="container"
        v-for="link in links"
        :key="link.label"
        :id="link.id"
      >
        <span>{{link.label}}</span>
      </div>
    </div>
  </div>
</template>

<style>
html,body {margin:0}
body {
  margin: 10px;
  border: 1px solid #ccc;
}
.scroll-wrap {
  height: 500px;
  padding: 10px;
  overflow: auto;
  background-color: #f5f7f9;
}
.scroll-view {
  min-height: 3000px;
}
.nav {
  padding: 10px;
  background-color: #fff;
  box-shadow: rgb(221 221 221 / 50%) 0px 2px 4px 0px;
}
.menu-item {
  padding-right: 10px;
  font-size: 16px;
  color: #222;
  line-height: 22px;
  cursor: pointer;
}
.menu-item + .menu-item {
  padding-left: 10px;
  border-left: 1px solid #ccc;
}
.menu-item.active {color:#387FE5}
.container {
  padding: 10px;
  border-radius: 6px;
  background-color: #fff;
  min-height: 300px;
}
.container + .container {
  margin-top: 10px;
}
</style>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3和Element Plus提供了一种简单的方法来实现侧边菜单栏与标签页之间的联动。下面是一个基本示例,演示了如何实现这一功能: 1. 首先,确保你已经安装了Vue 3和Element Plus,并在项目中引入它们。 2. 创建一个侧边菜单栏组件(SideMenu),用于展示菜单项。这个组件可以使用Element Plus的Menu组件来创建。 ```html <template> <el-menu :default-active="activeMenu" @select="handleMenuSelect"> <el-menu-item v-for="item in menuItems" :key="item.path" :index="item.path"> {{ item.name }} </el-menu-item> </el-menu> </template> <script> export default { data() { return { activeMenu: '', // 当前选中的菜单项 menuItems: [ { name: '菜单1', path: '/menu1' }, { name: '菜单2', path: '/menu2' }, // 其他菜单项... ] } }, methods: { handleMenuSelect(index) { this.activeMenu = index; // 更新选中的菜单项 this.$router.push(index); // 导航到对应的路由 } } } </script> ``` 3. 创建一个标签页组件(Tabs),用于展示已打开的页面。这个组件可以使用Element Plus的Tabs组件来创建。 ```html <template> <el-tabs v-model="activeTab" type="border-card" @tab-remove="handleTabRemove"> <el-tab-pane v-for="tab in openedTabs" :key="tab.path" :label="tab.name" :name="tab.path"> <!-- 页面内容 --> </el-tab-pane> </el-tabs> </template> <script> export default { data() { return { activeTab: '', // 当前选中的标签页 openedTabs: [] // 已打开的标签页 } }, methods: { addTab(tab) { const index = this.openedTabs.findIndex(item => item.path === tab.path); if (index === -1) { this.openedTabs.push(tab); } this.activeTab = tab.path; // 选中新打开的标签页 }, removeTab(targetName) { const index = this.openedTabs.findIndex(item => item.path === targetName); if (index !== -1) { this.openedTabs.splice(index, 1); } }, handleTabRemove(targetName) { this.removeTab(targetName); if (targetName === this.activeTab) { this.activeTab = this.openedTabs[this.openedTabs.length - 1].path; } } } } </script> ``` 4. 在你的主页面中,使用以上两个组件来实现联动效果。 ```html <template> <div> <side-menu></side-menu> <tabs></tabs> </div> </template> <script> import SideMenu from './SideMenu.vue'; import Tabs from './Tabs.vue'; export default { components: { SideMenu, Tabs } } </script> ``` 在这个例子中,当你点击侧边菜单栏的菜单项时,会更新选中的菜单项,并导航到对应的路由。同时,会在标签页中打开一个新的标签页。如果你点击已打开的标签页的关闭按钮,会关闭该标签页并自动选中最后一个打开的标签页。 这样就实现了侧边菜单栏与标签页的联动效果。你可以根据自己的需求进行定制和扩展。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值