Vue实现响应式导航菜单:桌面端导航栏 + 移动端抽屉式菜单

news/2024/11/20 22:33:09/

在现代Web开发中,为了提升用户体验,响应式设计已成为必备技能。本文将通过Vue.js,创建一个响应式导航菜单,桌面端显示顶部导航栏,移动端则切换为抽屉式菜单,并具备点击遮罩关闭的功能。以下是具体实现步骤。


项目需求分析

我们希望实现以下功能: 1. 桌面端宽屏(大于 768px):顶部导航菜单,水平布局,导航栏固定在页面顶部。 2. 移动端窄屏(小于或等于 768px):隐藏顶部导航栏,显示抽屉式菜单,点击遮罩层或关闭按钮可关闭抽屉。 3. 响应式设计:根据屏幕宽度自动切换布局,实时监听窗口大小变化。


实现步骤

1. 创建 Vue 项目并初始化布局

首先,初始化 Vue 项目。以下是 HTML 模板的基础结构,包含桌面端和移动端的两种菜单形式:

<template><div id="app"><!-- 顶部导航栏(仅桌面端显示) --><header><nav class="top-nav" v-if="!isMobile"><ul class="menu-list"><li v-for="(item, index) in menuItems" :key="index"><a href="#">{{ item.title }}</a></li></ul></nav><!-- 菜单按钮(仅移动端显示) --><button v-if="isMobile" class="menu-button" @click="toggleDrawer">☰</button></header><!-- 抽屉式菜单 --><div class="drawer" :class="{ open: isDrawerOpen }"><div class="drawer-header"><span class="logo">导航菜单</span><button class="close-button" @click="toggleDrawer">×</button></div><ul class="menu-list"><li v-for="(item, index) in menuItems" :key="index"><a href="#">{{ item.title }}</a></li></ul></div><!-- 抽屉遮罩层 --><div v-if="isMobile && isDrawerOpen" class="overlay" @click="closeDrawer"></div></div>
</template>

如果有二级菜单需要去做一些优化修改,使用css鼠标hover显示子级菜单或者通过js控制子级菜单展开折叠,以下是一个vue模版:

<template><div id="app"><!-- 菜单按钮 --><button class="menu-button" @click="toggleDrawer">☰</button><!-- 抽屉菜单 --><div class="drawer" :class="{ open: isDrawerOpen }"><div class="drawer-header"><span class="logo">Blog</span><button class="close-button" @click="toggleDrawer">×</button></div><ul class="menu-list"><li v-for="(item, index) in menuItems" :key="index" class="menu-item"><div class="menu-title" @click="toggleItem(index)"><span>{{ item.title }}</span><span v-if="item.submenu" class="arrow">{{ openIndex === index ? "▲" : "▼" }}</span></div><ul v-if="item.submenu && openIndex === index" class="submenu"><li v-for="(subItem, subIndex) in item.submenu" :key="subIndex">{{ subItem }}</li></ul></li></ul></div></div>
</template>
<script>
export default {data() {return {isDrawerOpen: false, // 抽屉是否打开openIndex: null, // 当前展开的菜单索引menuItems: [{ title: "🏠 首页" },{ title: "📱 科技社", submenu: ["互联网漫谈", "科技动态"] },{ title: "🎁 福利社", submenu: ["优惠活动", "每日抽奖"] },{ title: "🧰 资源社", submenu: ["学习资料", "工具下载"] },{ title: "💬 有话说" },{ title: "👭 友情频道" },{ title: "🍺 关于小站", submenu: ["站点介绍", "联系我们"] },],};},methods: {toggleDrawer() {this.isDrawerOpen = !this.isDrawerOpen; // 切换抽屉状态},toggleItem(index) {// 展开或折叠二级菜单this.openIndex = this.openIndex === index ? null : index;},},
};
</script>
<style scoped>
body {margin: 0;font-family: Arial, sans-serif;
}.menu-button {position: fixed;top: 16px;left: 16px;font-size: 24px;background: none;border: none;cursor: pointer;
}.drawer {position: fixed;top: 0;left: 0;width: 75%;height: 100%;background-color: white;transform: translateX(-100%);transition: transform 0.3s ease;box-shadow: 2px 0 8px rgba(0, 0, 0, 0.2);
}.drawer.open {transform: translateX(0);
}.drawer-header {display: flex;justify-content: space-between;align-items: center;padding: 16px;background-color: #f5f5f5;border-bottom: 1px solid #ddd;
}.logo {font-size: 20px;font-weight: bold;
}.close-button {background: none;border: none;font-size: 24px;cursor: pointer;
}.menu-list {list-style: none;padding: 0;margin: 0;
}.menu-item {padding: 16px;display: flex;flex-direction: column;justify-content: space-between;align-items: center;cursor: pointer;border-bottom: 1px solid #ddd;
}.menu-title {width: 100%;
}.submenu {width: 100%;list-style: none;padding: 0 16px;margin: 0;padding: 0 16px;background-color: #f9f9f9;
}.submenu li {padding: 8px 0;border-bottom: 1px solid #eee;
}.arrow {font-size: 12px;
}
</style>

2. 使用 Vue 管理状态

在脚本部分,我们通过 data 定义了抽屉状态 isDrawerOpen 和当前是否是移动端的标志 isMobile,并通过 methods 处理逻辑,包括菜单开关和窗口大小监听。

<script>
export default {data() {return {isDrawerOpen: false, // 抽屉是否打开isMobile: false,     // 当前是否是移动端menuItems: [{ title: "🏠 首页" },{ title: "📱 科技社" },{ title: "🎁 福利社" },{ title: "🧰 资源社" },{ title: "💬 有话说" },{ title: "👭 友情频道" },{ title: "🍺 关于小站" },],};},methods: {toggleDrawer() {this.isDrawerOpen = !this.isDrawerOpen; // 切换抽屉开关},closeDrawer() {this.isDrawerOpen = false; // 关闭抽屉},checkScreenSize() {this.isMobile = window.innerWidth <= 768; // 判断是否为移动端},},mounted() {this.checkScreenSize(); // 初次加载时检查屏幕尺寸window.addEventListener("resize", this.checkScreenSize); // 监听窗口大小变化},beforeDestroy() {window.removeEventListener("resize", this.checkScreenSize); // 组件销毁时移除监听器},
};
</script>

3. 添加样式

为实现桌面端顶部导航栏和移动端抽屉菜单,我们需要分别设置两种样式。

<style scoped>
/* 通用样式 */
body {margin: 0;font-family: Arial, sans-serif;
}/* 顶部导航栏样式(桌面端) */
.top-nav {position: fixed;top: 0;left: 0;width: 100%;background-color: #f5f5f5;padding: 16px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);z-index: 1000;
}.top-nav .menu-list {display: flex;justify-content: flex-start;list-style: none;margin: 0;padding: 0;
}.top-nav .menu-list li {margin-right: 20px;
}.top-nav .menu-list li a {text-decoration: none;color: #333;
}/* 移动端抽屉菜单样式 */
.menu-button {font-size: 24px;background: none;border: none;cursor: pointer;
}.drawer {position: fixed;top: 0;left: 0;width: 75%;height: 100%;background-color: white;transform: translateX(-100%);transition: transform 0.3s ease;box-shadow: 2px 0 8px rgba(0, 0, 0, 0.2);z-index: 1000;
}.drawer.open {transform: translateX(0);
}.drawer-header {display: flex;justify-content: space-between;align-items: center;padding: 16px;background-color: #f5f5f5;border-bottom: 1px solid #ddd;
}.menu-list {list-style: none;padding: 0;margin: 0;
}.menu-list li {padding: 16px;border-bottom: 1px solid #ddd;
}.menu-list li a {text-decoration: none;color: #333;
}/* 遮罩层 */
.overlay {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.5);z-index: 999;
}/* 响应式样式 */
@media (max-width: 768px) {.top-nav {display: none; /* 隐藏桌面端导航 */}
}
</style>

4. 完整代码

整合模板、脚本和样式,完整代码如下:

<template><div id="app"><header><nav class="top-nav" v-if="!isMobile"><ul class="menu-list"><li v-for="(item, index) in menuItems" :key="index"><a href="#">{{ item.title }}</a></li></ul></nav><button v-if="isMobile" class="menu-button" @click="toggleDrawer">☰</button></header><div class="drawer" :class="{ open: isDrawerOpen }"><div class="drawer-header"><span class="logo">导航菜单</span><button class="close-button" @click="toggleDrawer">×</button></div><ul class="menu-list"><li v-for="(item, index) in menuItems" :key="index"><a href="#">{{ item.title }}</a></li></ul></div><div v-if="isMobile && isDrawerOpen" class="overlay" @click="closeDrawer"></div></div>
</template><script>
export default {data() {return {isDrawerOpen: false,isMobile: false,menuItems: [{ title: "🏠 首页" },{ title: "科技社" },{ title: "🎁 福利社" },{ title: "🧰 资源社" },{ title: "💬 北城有话说" },{ title: "✈️ TG订阅频道" },{ title: "🍺 关于小站" },],};},methods: {toggleDrawer() {this.isDrawerOpen = !this.isDrawerOpen;},closeDrawer() {this.isDrawerOpen = false;},checkScreenSize() {this.isMobile = window.innerWidth <= 768;},},mounted() {this.checkScreenSize();window.addEventListener("resize", this.checkScreenSize);},beforeDestroy() {window.removeEventListener("resize", this.checkScreenSize);},
};
</script><style scoped>
/* 样式同上 */
</style>

运行效果

  1. 桌面端:显示水平导航菜单,固定在页面顶部。
  2. 移动端:显示抽屉式菜单,点击按钮展开,点击遮罩关闭。

通过这个例子,我们实现了一个功能完备、易于扩展的响应式导航菜单,你可以根据需求进一步美化样式或添加其他功能!


http://www.ppmy.cn/news/1548590.html

相关文章

MSTP知识点

多生成树协议 在 MSTP&#xff08;Multiple Spanning Tree Protocol&#xff09;中&#xff0c;根桥&#xff08;root&#xff09;、指定端口&#xff08;designated port&#xff09;、备用端口&#xff08;alternate port&#xff09;等角色都是确保网络中没有循环并且流量能…

【漏洞复现】某全新H5购物商城系统存在前台任意文件上传漏洞(RCE)

漏洞描述 该源码采用HTML5技术开发,可以完美适配各种移动设备,以及iOS和Android系统。同时,易支付接口更为商家提供了便捷的交易功能,让顾客可以轻松通过手机进行网络支付,享受到更加便捷的购物体验。该源码界面设计十分简洁、清爽,同时还保证了购物流程的顺畅和简便。无…

爬虫日常练习

1.反webdriver自动化检测爬取 有的网站会有检测webdriver的反爬手段&#xff0c;这时候就需要做一些操作防止被网页检测到&#xff0c;下面直接给出固定代码段方法&#xff1a; from selenium.webdriver.support.ui import WebDriverWait# 配置 ChromeOptions 防止被检测 optio…

lua调用C语言函数,在函数中进行类型检查

使用lua_is*函数族进行检查&#xff08;除了lua_type之外的另一种方式&#xff09; Lua C API提供了一系列lua_is*函数&#xff0c;如lua_isnumber、lua_isstring、lua_isboolean等&#xff0c;用于检查栈上元素的类型。示例代码如下&#xff0c;假设我们有一个C函数&#xff0…

LabVIEW三针自动校准系统

基于LabVIEW的智能三针自动校准系统采用非接触式激光测径仪对标准三针进行精确测量。系统通过LabVIEW软件平台与硬件设备的协同工作&#xff0c;实现了数据自动采集、处理及报告生成&#xff0c;大幅提高了校准精度与效率&#xff0c;并有效降低了人为操作误差。 一、项目背景…

ITSS服务经理: 山西科技学院智能铸造现代产业学院揭牌

记者从山西科技学院传来喜讯&#xff0c;近日&#xff0c;在该院工程训练中心与智能铸造现代产业学院于山西省晋城市泽州县绿色智能铸造创新产业园隆重举行的揭牌启动仪式上&#xff0c;标志着学院迈入崭新篇章。应用型本科高校&#xff0c;作为孕育高素质应用人才的摇篮&#…

25. 架构能力

文章目录 第25章 架构能力25.1 个人能力&#xff1a;架构师的职责、技能和知识职责技能知识那经验方面呢&#xff1f; 25.2 软件架构组织的能力25.3 成为更优秀的架构师接受指导指导他人 25.4 小结25.5 扩展阅读25.6 问题讨论 第25章 架构能力 人生苦短&#xff0c;学海无涯。 …

在Linux环境下部署TiDB可以通过几种不同的方法

在Linux环境下部署TiDB可以通过几种不同的方法&#xff0c;包括使用TiDB官方提供的二进制包、Docker容器、Kubernetes等。最常见的方法是使用TiDB官方的二进制包&#xff0c;下面将详细介绍如何在Linux系统上手动部署TiDB。 前提条件 操作系统&#xff1a;Linux&#xff08;例…