顶部动态菜单栏的使用

效果图

开发环境

vue3

关键逻辑

复制代码
//导航栏状态选择
const navbarSolid = ref(false);
//初始化导航栏高度
const navbarHeight = ref(0);

/**
 * 根据滚动距离改变样式
 */
function checkNavbarOpacity() {
  navbarSolid.value = window.pageYOffset > navbarHeight.value / 2;
}

/**
 * 绑定window的scroll事件
 */
onMounted(() => {
  // 获取导航栏高度
  navbarHeight.value = document.querySelector('nav').offsetHeight;
  window.addEventListener('scroll', checkNavbarOpacity);
});
/**
 * 解绑window的scroll事件
 */
onUnmounted(() => {
  window.removeEventListener('scroll', checkNavbarOpacity);
});

实现代码

复制代码
<template>
  <nav :class="{ 'afterNav': navbarSolid, 'beforeNav': !navbarSolid }">
    <div class="text">
      <span class="nav-logo" @click="router.push('/')">月木天上</span>
      <div class="nav-list">
        <div class="nav-item" v-for="(nav,index) in navList" :key="index">
          <span @click="router.push(nav.path)">{{ nav.name }}</span>
        </div>
      </div>
    </div>
  </nav>
</template>
<script setup>
import {onMounted, onUnmounted, reactive, ref} from 'vue';
import {useDataStore} from "@/stores/dataStore"
import {useRouter} from "vue-router";

const router = useRouter()
const dataStore = useDataStore()
//初始化导航列表
const navList = reactive([
  {
    name: '首页',
    path: '/home/index'
  },
  {
    name: '导航',
    path: '/home/nav'
  },
  {
    name: '课程',
    path: '/course/index'
  },
  {
    name: '博客',
    path: '/blog/index'
  },
  {
    name: '商城',
    path: '/shop/index'
  },
  {
    name: '联系我们',
    path: '/home/contact'
  },

])
//导航栏状态选择
const navbarSolid = ref(false);
//初始化导航栏高度
const navbarHeight = ref(0);

/**
 * 根据滚动距离改变样式
 */
function checkNavbarOpacity() {
  navbarSolid.value = window.pageYOffset > navbarHeight.value / 2;
}

/**
 * 绑定window的scroll事件
 */
onMounted(() => {
  // 获取导航栏高度
  navbarHeight.value = document.querySelector('nav').offsetHeight;
  window.addEventListener('scroll', checkNavbarOpacity);
});
/**
 * 解绑window的scroll事件
 */
onUnmounted(() => {
  window.removeEventListener('scroll', checkNavbarOpacity);
});

</script>
<style scoped lang="scss">
/* 初始样式 */
.beforeNav {
  position: fixed;
  width: 100%;
  transition: background-color 0.3s;

  .text {
    margin-top: 30px;

    .nav-logo {
      color: #fff;
      float: left;
      margin-left: 12%;
      font-family: 楷体;
      font-weight: bolder;
      font-size: 2em;
    }

    .nav-logo:hover {
      cursor: pointer;
    }

    .nav-list {
      display: flex;
      margin-left: 49%;

      .nav-item {
        margin-left: 30px;
        font-family: 楷体;
        font-size: 1.5em;
        color: #a5d2e3;
      }

      .nav-item:hover {
        text-decoration: underline;
        cursor: pointer; /*变小手*/
        color: #ffffff;
      }
    }
  }
}

/* 下拉后样式 */
.afterNav {
  background-color: #ffffff;
  z-index: 100;
  position: fixed;
  width: 100%;
  transition: background-color 0.3s;
  box-shadow: 0 0 9px 0 rgb(0 0 0 / 10%);

  .text {
    margin-top: 15px;
    margin-bottom: 15px;

    .nav-logo {
      color: #52d3aa;
      float: left;
      margin-left: 12%;
      font-family: 楷体;
      font-weight: bolder;
      font-size: 2em;
    }

    .nav-logo:hover {
      cursor: pointer;
    }

    .nav-list {
      display: flex;
      margin-left: 50%;

      .nav-item {
        margin-left: 30px;
        font-family: 楷体;
        font-size: 1.5em;
        color: #7f7f7f;
      }

      .nav-item:hover {
        text-decoration: underline;
        cursor: pointer; /*变小手*/
        color: #52d3aa;
      }
    }
  }
}


</style>
相关推荐
hpoenixf31 分钟前
2026 年前端面试问什么
前端·面试
还是大剑师兰特38 分钟前
Vue3 中的 defineExpose 完全指南
前端·javascript·vue.js
泯泷1 小时前
阶段一:从 0 看懂 JSVMP 架构,先在脑子里搭出一台最小 JSVM
前端·javascript·架构
mengchanmian2 小时前
前端node常用配置
前端
华洛2 小时前
利好打工人,openclaw不是企业提效工具,而是个人助理
前端·javascript·产品经理
xkxnq2 小时前
第六阶段:Vue生态高级整合与优化(第93天)Element Plus进阶:自定义主题(变量覆盖)+ 全局配置与组件按需加载优化
前端·javascript·vue.js
A黄俊辉A3 小时前
vue css中 :global的使用
前端·javascript·vue.js
小码哥_常3 小时前
被EdgeToEdge适配折磨疯了,谁懂!
前端
小码哥_常3 小时前
从Groovy到KTS:Android Gradle脚本的华丽转身
前端
灵感__idea4 小时前
Hello 算法:复杂问题的应对策略
前端·javascript·算法