前端H5移动端基础框架模板 :Vue3 + Vite5 + Pinia + Vant4 + Sass + 附源码

技术栈选用 Vue3 + Vite5 + Pinia + Vant4 + Sass

源码地址:

git clone https://gitee.com/gaiya001/h5-APP.git

在这里插入图片描述
在这里插入图片描述

1. 1.vite.config.js文件配置

**

import { defineConfig } from 'vite' // 导入 Vite 的配置函数
import vue from '@vitejs/plugin-vue' // 导入 Vue 插件
import path from 'path' // 导入 Node.js 的 path 模块
import Components from 'unplugin-vue-components/vite' // 导入 Vue 组件自动注册插件
import { VantResolver } from 'unplugin-vue-components/resolvers' // 导入 Vant 组件解析器
import { visualizer } from 'rollup-plugin-visualizer' // 导入 Rollup 打包分析插件
import { execSync } from 'child_process' // 导入 Node.js 的 child_process 模块export default defineConfig({base: '/', // 设置应用的基础路径server: {port: 3000, // 设置开发服务器端口open: true, // 启动开发服务器时自动打开浏览器proxy: {'/api': {target: 'https://baidu', // 设置代理的目标地址changeOrigin: true, // 改变请求的源头rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径},},},plugins: [vue(), // 使用 Vue 插件Components({resolvers: [VantResolver()], // 使用 Vant 组件解析器自动注册 Vant 组件}),visualizer({ open: true }), // 使用打包分析工具并在打包后自动打开分析报告],resolve: {alias: {'@': path.resolve(__dirname, './src'), // 设置路径别名,@ 指向 src 目录},},build: {rollupOptions: {output: {manualChunks: {vendor: ['vue', 'axios', 'vant'], // 手动分割 vendor 包,包含 vue, axios, vant},},},chunkSizeWarningLimit: 500, // 设置警告阈值,单位 KBbrotliSize: false, // 关闭 Brotli 压缩大小报告},optimizeDeps: {include: ['vue', 'axios', 'vant'], // 预构建依赖,提高构建速度},// 添加打包完成后清除 log 文件的钩子buildEnd: () => {try {execSync('rimraf logs'); // 使用 rimraf 清除 logs 目录// console.log('日志文件已清除');} catch (error) {// console.error('清除日志文件失败:', error);}},
})

2.main.js文件配置详解

// 导入 Vue 的 createApp 函数,用于创建 Vue 应用实例
import { createApp } from 'vue';// 导入根组件 App.vue
import App from './App.vue';// 引入路由配置
import router from './router/index.js';// 引入路由权限配置
import '@/router/permission.js';// 引入 Vant 的样式文件
import 'vant/lib/index.css';// 引入全局样式文件(使用 SCSS)
import './assets/index.sass';// 引入 Pinia 实例
import pinia from './store/index.js';// 创建 Vue 应用实例
const app = createApp(App);// 使用路由插件
app.use(router);// 使用 Pinia 插件
app.use(pinia);// 将 Pinia 实例注册为全局属性(可选)
// app.config.globalProperties.$store = pinia;// 挂载应用到 DOM 中的 #app 元素
app.mount('#app');## ```3.axios-req.js文件详解```javascript
// 导入 axios 库,用于发送 HTTP 请求
import axios from 'axios';// 从 Vant 库中导入 Toast 和 Dialog 组件,用于显示提示信息和对话框
import { Toast, Dialog } from 'vant';// 从 Pinia 存储中导入 basic store,用于管理全局状态
import { useBasicStore } from '@/store/basic';// 创建 axios 请求实例
const service = axios.create({baseURL: import.meta.env.VITE_APP_BASE_URL, // 设置基础 URL,从环境变量中获取timeout: 12000 // 设置请求超时时间为 12000 毫秒
});let loadingInstance = null; // 用于存储 loading 提示实例
let tempReqUrlSave = ''; // 临时保存请求 URL
let authorTipDoor = true; // 控制授权提示的开关// 定义一个函数,用于处理未授权的情况
const noAuthDill = () => {authorTipDoor = false; // 关闭授权提示开关Dialog.confirm({message: '请重新登录', // 提示信息confirmButtonText: '重新登录', // 确认按钮文本closeOnClickOverlay: false, // 点击遮罩层不关闭对话框showCancelButton: false, // 不显示取消按钮showClose: false, // 不显示关闭按钮theme: 'round-button' // 对话框主题}).then(() => {useBasicStore().resetStateAndToLogin(); // 重置状态并跳转到登录页面authorTipDoor = true; // 重新打开授权提示开关});
};// 请求前拦截器
service.interceptors.request.use((req) => {const { token, axiosPromiseArr } = useBasicStore();// 收集请求地址,用于取消请求req.cancelToken = new axios.CancelToken((cancel) => {tempReqUrlSave = req.url;axiosPromiseArr.push({url: req.url,cancel});});// 设置 token 到请求头if (token) req.headers['X-Auth-Token'] = token;// 如果请求方法是 GET 并且没有 params,使用 data 作为 paramsif (req.method?.toLowerCase() === 'get' && !req.params) req.params = req.data;// 请求加载提示if (req.reqLoading ?? true) {loadingInstance = Toast.loading({forbidClick: true, // 禁止点击duration: 0, // 持续时间,0 表示持续显示message: '数据载入中...' // 提示信息});}console.log('Request:', req); // 添加请求日志return req;},(err) => {console.error('Request Error:', err); // 添加请求错误日志return Promise.reject(err);}
);// 请求后拦截器
service.interceptors.response.use((res) => {// 取消请求useBasicStore().remotePromiseArrByReqUrl(tempReqUrlSave);if (loadingInstance) {Toast.clear(); // 清除 loading 提示}// 处理文件下载if (res.data?.type?.includes("sheet")) {return res;}const { code, msg } = res.data;const successCode = [0, 200, 20000]; // 成功状态码const noAuthCode = [401, 403]; // 未授权状态码if (successCode.includes(code)) {console.log('Response:', res); // 添加响应日志return res.data;} else {// authorTipDoor 防止多个请求多次提示if (authorTipDoor) {if (noAuthCode.includes(code)) {noAuthDill(); // 处理未授权情况} else {if (!res.config?.isNotTipErrorMsg) {Toast.fail({message: msg || '请求失败', // 提示信息duration: 2 * 1000 // 持续时间 2 秒});} else {return res;}return Promise.reject(msg || '请求失败');}}}},(err) => {// 取消请求useBasicStore().remotePromiseArrByReqUrl(tempReqUrlSave);if (loadingInstance) {Toast.clear(); // 清除 loading 提示}console.error('Response Error:', err); // 添加响应错误日志Toast.fail({message: err.message || '网络请求失败', // 提示信息duration: 2 * 1000 // 持续时间 2 秒});return Promise.reject(err);}
);// 手动取消请求
export function cancelRequest(url) {const { axiosPromiseArr } = useBasicStore();const index = axiosPromiseArr.findIndex(item => item.url === url);if (index !== -1) {axiosPromiseArr[index].cancel(); // 取消请求axiosPromiseArr.splice(index, 1); // 从数组中移除已取消的请求}
}// 导出 service 实例给页面调用,config -> 页面的配置
export default function axiosReq(config) {return service(config);
}

4.路由permission.js文件配置

import router from './index'; // 引入主路由模块
import { useUserStore } from '@/store/modules/user'; // pinia持久化的信息const whiteList = ['/login']; // 不需要鉴权的路由白名单router.beforeEach(async (to, from, next) => {console.log(to,"路由前置守望");const userStore = useUserStore();// 设置页面标题document.title = to.meta?.title;// 获取用户信息const { token } = userStore.userInfo;console.log(token,'token')// 如果用户已经登录,则直接放行if (token) {next();return;}// 如果用户未登录并且目标路由不在白名单中if (!token && !whiteList.includes(to.path)) {// 重定向到登录页,并携带当前路由路径作为查询参数next(`/login?redirect=${to.path}`);} else {// 目标路由在白名单中,直接放行next();}
});
// 路由后置守卫
router.afterEach((to, from) => {// console.log('路由后置守望', to, from);
});export default router;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/488397.html

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

相关文章

游戏引擎学习第36天

仓库 :https://gitee.com/mrxiao_com/2d_game 回顾之前的内容 在这个程序中,目标是通过手动编写代码来从头开始制作一个完整的游戏。整个过程不使用任何库或现成的游戏引擎,这样做的目的是为了能够全面了解游戏执行的每一个细节。开发过程中&#xff0…

C++小碗菜之五:GDB调试工具

“程序员不是编写代码的人,而是调试错误的人。” – 约翰本尼斯(John Bennet) 目录 前言 在虚拟机中安装 GDB GDB调试的实战演练 创建示例代码 例子: 使用 GDB 调试 编译代码 启动 GDB 设置断点 运行程序 打印变量值 …

【软件测试面试题】测试理论/基础面试(持续更新)

Hi,大家好。最近很多朋友都在说今年的互联网行情不好,面试很难,不知道怎么复习,我最近总结了一份在软件测试面试中比较常见的测试理论/基础面试面试题合集,希望对大家有帮助。建议点赞收藏再阅读,防止丢失&…

(css)element中el-select下拉框整体样式修改

(css)element中el-select下拉框整体样式修改 重点代码(颜色可行修改) // 修改input默认值颜色 兼容其它主流浏览器 /deep/ input::-webkit-input-placeholder {color: rgba(255, 255, 255, 0.50); } /deep/ input::-moz-input-placeholder {color: rgba…

十一、容器化 vs 虚拟化-Docker

文章目录 前言一、Docker 介绍1. 简介2. 应用场景3. 特点4. Docker和虚拟机之间的区别5. 解决痛点1. 解决依赖兼容2. 解决操作系统环境差异3. 小结 二、Docker 架构三、工作流程五、Docker 核心组件及其工作机制1. Docker 客户端(Docker Client)2. Docke…

游戏引擎学习第38天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾上次的内容。 我们之前讨论了将精灵放在屏幕上,但颜色错误的问题。问题最终查明是因为使用了一个调整工具,导致文件的字节顺序发生了变化。重新运行“image magic”工具对一些大图像进行重新处理后&am…

Docker 安装Nginx与配置Nginx

文章目录 前言 1.什么是nginx2.为什么使用nginx3.高并发4.Nginx特点: 一、docker安装nginx二、Nginx配置简介 1.文件讲解2.nginx.conf3.default.conf 三、nginx负载均衡 1.配置服务器列表地址2.多集群策略 2.1 权重配置2.2 ip_hash2.3 least_conn2.4 fair2.5 url_h…

qwen2.5 模型JSON格式化输出案例

这篇不是通过prompt提示去实现,是用vllm、ollama推理框架支持;这里也给出个prompt实现的案例参考 1、 vllm推理 参考:https://docs.vllm.ai/en/latest/usage/structured_outputs.html 模型vllm运行: 用的Qwen/Qwen2.5-3B-Instruct模型 vllm serve ./qwen2_5 --host 0.0…

黑马商城微服务复习(6)

MQ高级 1. 消息可靠性2. 发送者的可靠性1. 发送者问题2. 生产者重试机制3. 生产者确认机制4. MQ可靠性5. 消费者的可靠性 3. 延迟消息1. 定义2. 死信交换机 1. 消息可靠性 发送消息时丢失: 生产者发送消息时连接MQ失败生产者发送消息到达MQ后未找到Exchange生产者发…

UE5.5 Geometry库平面切割原理分析

平面切割--FMeshPlaneCut 平面定义: 面上一个点 法线 算法流程如下 求几何体所有顶点和面的有向距离(Signs) Sign计算: float Sign (VertexPos - PlaneOrigin).Dot(PlaneNormal); 遍历所有几何体所有交叉边, 进行SplitEdge 对于位于切割面两侧的交叉边(Sign…

TMS Software:TMS BIZ产品——TMS XData

TMS XData 用于多层REST/JSON HTTP/HTTPS应用服务器开发和ORM远程处理的Delphi框架。 TMS扩展数据可同时用于以下框架: VCLWEBFMX TMS XData可同时用于以下操作系统/浏览器: TMS XData可同时用于以下IDE: 功能概述 基于REST/JSON架构风格的…

优化移动端H5:常见问题与解决方案

移动端H5开发中的“坑”与解决方案 本文介绍了开发中遇到的几个关于移动端H5开发中的小问题,以及解决的方法。 一、iOS滑动不流畅问题 在iOS设备上,H5页面的滑动效果有时会出现不流畅的情况,特别是在页面高度超过一屏时。这通常是由于iOS的…

【论文速读】| AttackQA:利用微调及开源大语言模型辅助网络安全运营的数据集的开发与应用

基本信息 原文标题: AttackQA: Development and Adoption of a Dataset for Assisting Cybersecurity Operations Using Fine-Tuned and Open-Source LLMs 原文作者: Varun Badrinath Krishna 作者单位: SambaNova Systems 关键词: 网络安全、检索增强生成(RAG&…

Ubuntu24.04配置STMTrack

项目地址:https://github.com/fzh0917/STMTrack 一、安装 CUDA 参考链接: Ubuntu24.04配置DINO-Tracker Ubuntu多CUDA版本安装及切换 由于之前在其他项目中已经安装了 CUDA12.1,这次需要安装另一个版本。 1. 查看安装版本 按照 requireme…

服务器数据恢复—热备盘上线过程中硬盘离线导致raid5阵列崩溃的数据恢复案例

服务器数据恢复环境: 两组分别由4块SAS接口硬盘组建的raid5阵列,两组raid5阵列划分LUN并由LVM管理,格式化为EXT3文件系统。 服务器故障: RAID5阵列中一块硬盘未知原因离线,热备盘自动激活上线替换离线硬盘。在热备盘上…

【Java学习笔记】Map接口和常用方法

一、 Map接口实现类的 特点[很实用] key是自己存的java对象 value是一个固定的 //当有相同的 k ,就等价于替换. 二、 Map常用方法 (根据键–>k) 三、Map接口遍历方法 package com.hspedu.map_; import java.util.*; /** * author 韩顺平 * ver…

1.网络知识-IP与子网掩码的关系及计算实例

IP与子网掩码 说实话,之前没有注意过,今天我打开自己的办公地电脑,看到我的网络配置如下: 我看到我的子网掩码是255.255.254.0,我就奇怪了,我经常见到的子网掩码都是255.255.255.0啊?难道公司配…

SpringBoot中bean的生命周期

文章目录 概述使用场景代码演示bean初始化TestSupportBeanPostProcessorImpllog 代码 概述 Bean 生命周期管理是 Spring Boot 中的关键功能之一。它负责管理应用程序中的 Java 对象,这些对象被称为 Beans。Spring Boot 通过创建、配置、初始化和销毁这些 Beans 来确…

【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:编写一个程序利用栈判断左、右圆括号是否配对。 相关知识 为了完成本关任务,你需要掌握:栈对括号的处理。 栈对括号的处理 &…

让PPT不再“难搞”:智能工具如何改变办公体验

PPT的世界是一场属于设计感与逻辑力的双重较量。那些字体配色的小心思,排版设计的大考验,无不让人抓耳挠腮。然而,科技的加持让这一切正悄然改变。比如,随着 ai生成ppt 工具的兴起,许多复杂操作正被重新定义&#xff0…