顶部动态菜单栏的使用

效果图

开发环境

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>
相关推荐
我是日安2 分钟前
从零到一打造 Vue3 响应式系统 Day 10 - 为何 Effect 会被指数级触发?
前端·vue.js
知了一笑2 分钟前
「AI」网站模版,效果如何?
前端·后端·产品
艾小码5 分钟前
用了这么久React,你真的搞懂useEffect了吗?
前端·javascript·react.js
知觉6 分钟前
实现@imput支持用户输入最多三位整数,最多一位小数的数值
前端
RoyLin6 分钟前
TypeScript设计模式:状态模式
前端·后端·typescript
RoyLin8 分钟前
TypeScript设计模式:观察者模式
前端·后端·typescript
干就完了110 分钟前
js对象常用方法都在这,使用时想不到?不存在的
前端·javascript
艾小码10 分钟前
还在硬邦邦跳转页面?Vue这3招让应用丝滑如德芙!
前端·javascript·vue.js
RoyLin12 分钟前
TypeScript设计模式:备忘录模式
前端·后端·typescript
阿笑带你学前端13 分钟前
Flutter本地通知系统:记账提醒的深度实现
前端·flutter