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

在现代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.rhkb.cn/news/474095.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac os 系统上如何开启远程登录的 ssh 22 端口

macOS 允许使用 SSH 连接&#xff0c;但为了安全起见&#xff0c;需要手动启动 SSH 服务&#xff0c;有两种方法可以激活远程登录。 方法一&#xff1a;界面化操作 1. 打开“系统偏好设置”&#xff0c;点击屏幕左上角的 Apple 图标&#xff0c;然后选择 系统偏好设置。 2. …

利用Python爬虫获取淘宝店铺详情

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。对于电商平台&#xff0c;尤其是淘宝这样的大型电商平台&#xff0c;店铺详情数据的获取和分析对于商家来说至关重要。它不仅可以帮助商家了解市场趋势&#xff0c;还可以优化营销策略&#xff0c;提升销售业绩。本文…

RabbitMQ教程:发布/订阅模式(Publish/Subscribe)(三)

文章目录 RabbitMQ教程&#xff1a;发布/订阅模式&#xff08;Publish/Subscribe&#xff09;&#xff08;三&#xff09;一、引言二、简介三、准备工作3.1 说明3.2 生成项目 四、实战4.1 交换机&#xff08;Exchanges&#xff09;4.2 临时队列&#xff08;Temporary Queues&am…

对PolyMarket的突袭

一天清晨六点&#xff0c;美国联邦调查局的探员冲进了纽约市的一间公寓。这间公寓的主人是26岁的Shane Copeland&#xff0c;一个有着凌乱头发的年轻人&#xff0c;也是一个加密货币狂热者。他运营着一个名为PolyMarket的网站——一个允许用户YZ全球事件结果的平台&#xff0c;…

DataStream编程模型之数据源、数据转换、数据输出

Flink之DataStream数据源、数据转换、数据输出&#xff08;scala&#xff09; 0.前言–数据源 在进行数据转换之前&#xff0c;需要进行数据读取。 数据读取分为4大部分&#xff1a; &#xff08;1&#xff09;内置数据源&#xff1b; 又分为文件数据源&#xff1b; socket…

Django5 2024全栈开发指南(三):数据库模型与ORM操作

目录 一、模型的定义二、数据迁移三、数据表关系四、数据表操作4.1 Shell工具4.2 数据新增4.3 数据修改4.4 数据删除4.5 数据查询4.6 多表查询4.7 执行SQL语句4.8 数据库事务 Django 对各种数据库提供了很好的支持&#xff0c;包括 PostgreSQL、MySQL、SQLite 和 Oracle&#x…

ASP.NET Core Webapi 返回数据的三种方式

ASP.NET Core为Web API控制器方法返回类型提供了如下几个选择&#xff1a; Specific type IActionResult ActionResult<T> 1. 返回指定类型&#xff08;Specific type&#xff09; 最简单的API会返回原生的或者复杂的数据类型&#xff08;比如&#xff0c;string 或者…

网关在能源物联网中扮演了什么角色?

随着通信、物联网、云平台等技术的飞速发展&#xff0c;越来越多能源用户希望借助先进的管理手段&#xff0c;对能源进行分布式监测、集中管理&#xff0c;构建能源物联网。准确的分布式监测和集中管理有助于制定更科学合理的节能减排计划。企业或能源使用单位可以依据能源物联…

【快速入门】前端御三家:HTML、CSS和JS

HTML HTML&#xff0c;超文本标记语言&#xff0c;可以理解成骨架&#xff0c;是一个基础的东西。 一.基础结构 如图所示&#xff1a; 二.常见标签 1.标题标签 在页面上定义标题性的内容 <h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标…

WebSocket实战,后台修改订单状态,前台实现数据变更,提供前端和后端多种语言

案例场景&#xff1a; 在实际的后台中需要变更某个订单的状态&#xff0c;在官网中不刷新页面&#xff0c;可以自动更新状态 在前端页面实现订单状态的实时更新&#xff08;不刷新页面&#xff09;&#xff0c;可以通过 WebSocket 的方式与后台保持通信&#xff0c;监听订单状态…

Django5 2024全栈开发指南(二):Django项目配置详解

目录 一、基本配置信息二、资源文件配置2.1 资源路由——STATIC_URL2.2 资源集合——STATICFILES_DIRS2.3 资源部署——STATIC_ROOT2.2.4 媒体资源——MEDIA 三、模板配置四、数据库配置4.1 mysqlclient连接MySQL4.2 pymysql连接MySQL4.3 多个数据库的连接方式4.4 使用配置文件…

近几年新笔记本重装系统方法及一些注意事项

新笔记本怎么重装系统&#xff1f; 近几年的新笔记本默认开启了raid on模式或vmd选项&#xff0c;安装过程中会遇到问题&#xff0c;新笔记本电脑重装自带的系统建议采用u盘方式安装&#xff0c;默认新笔记本有bitlocker加密机制&#xff0c;如果采用一键重装系统或硬盘方式安装…

黑马智数Day10

项目背景说明 后台管理部分使用的技术栈是Vue2&#xff0c;前台可视化部分使用的技术栈是Vue3 前台可视化项目不是独立存在&#xff0c;而是和后台管理项目共享同一个登录页面 微前端的好处 微前端是一种前端架构模式&#xff0c;它将大型单体应用程序分解为小的、松散耦合的…

Visual Studio 圈复杂度评估

VisualStudio自带的有工具 之后就可以看到分析结果

prop校验,prop和data区别

prop:组件上注册的一些自定义属性 prop作用&#xff1a;向子组件传递数据 特点&#xff1a; 可以传递任意数量&#xff0c;任意类型的prop 父组件 &#xff08;一个个地传递比较麻烦&#xff0c;可以直接打包成一个对象传过去&#xff0c;然后通过点属性接收&#xff09; <t…

ubuntu显示管理器_显示导航栏

ubuntu文件管理器_显示导航栏 一、原始状态&#xff1a; 二、显示导航栏状态&#xff1a; 三、原始状态--->导航栏状态: 1、打开dconf编辑器&#xff0c;直接在搜索栏搜索 dconf-editor ------如果没有安装&#xff0c;直接按流程安装即可。 2、进入目录&#xff1a;org …

跨平台WPF框架Avalonia教程 一

安装 安装 Avalonia UI 模板​ 开始使用 Avalonia 的最佳方式是使用模板创建一个应用程序。 要安装 Avalonia 模板&#xff0c;请运行以下命令&#xff1a; dotnet new install Avalonia.Templates 备注 对于 .NET 6.0 及更早版本&#xff0c;请将 install 替换为 --inst…

UE5 材质里面画圆锯齿严重的问题

直接这么画圆会带来锯齿&#xff0c;我们对锯齿位置进行模糊 可以用smoothstep&#xff0c;做值的平滑过渡&#xff08;虽然不是模糊&#xff0c;但是类似&#xff09;

【MySql】实验十六 综合练习:图书管理系统数据库结构

文章目录 创建图书管理系统数据库结构一、创建数据表1.1 book表1.2 reader表1.3 borrow表 二、插入示例数据2.1 向book表插入数据2.2 向reader表插入数据2.3 向borrow表插入数据 三、查询操作3.1 根据语义为借书表borrow的bno列和 rno列建立外键3.2 查询张小海编写的“数据库原…

QT QLabel双击事件

新建类&#xff1a; DoubleClickLabel .h #pragma once#include <QLabel>class DoubleClickLabel : public QLabel {Q_OBJECTpublic:DoubleClickLabel(QWidget *parent);~DoubleClickLabel(); signals:void doubleClicked();protected: //这里重写双击事件virtual v…