vite-uniapp-template
🚀 基于 vitejs 驱动的 uniapp 最佳实践集成模板 查看演示
特点
- 💪 Assets: 提供了全局静态资源加载工具,无感切换加载本地静态资源/远程静态资源,解决小程序环境下包大小限制问题。
- 📦 SubPackages: 符合心智模型的分包风格,合理的 pages 目录结构,与分包配置轻松实现功能分包。
- 🛣 Router: 使用 uniapp-router-next,并通过优化封装,API 同 VueRouter 类似,扩展了拦截器、中间件、路由别名功能。
- 📊 Store: 使用 Pinia 强力驱动,轻松实现应用状态管理。
- ⚡️ Request: 请求库使用 uni-network 完全基于 uniapp API 编写的高性能请求库, API 同 axios。
- 👇 Z-paging: 内置了高性能且易于使用的业务常用下拉分页组件模块,轻松实现下拉刷新、上拉加载等功能。
- 💅 Unocss: 使用原子化 CSS 引擎,小程序环境下依然完美支持原子化的 class 命名书写规则。
- 🎨 UI-libs: 预设了 uv-ui 和 uni-ui 两者相辅相成,轻松满足绝大多数业务场景,并支持主题色定制功能。
- 📝 NoTs: 只使用 JavaScript,在常规业务场景或人员水平差距过大情况下,TypeScript 并不会提升开发体验。
使用方法
克隆项目
git clone https://github.com/viarotel/vite-uniapp-template.git
安装项目依赖
打开并进入克隆的项目根目录下执行以下命令
以下命令推荐 使用 pnpm 进行操作 不过你依然可以使用 npm/yarn
pnpm install
运行项目
任意编辑器直接运行本项目
# h5端
pnpm dev:h5
# 微信小程序端
pnpm dev:mp-weixin
# 安卓端
pnpm dev:app-android
#... 更多端请参阅 package.json/script
在 HBuilder 中运行本项目
- 将项目拖动到 HBuilder 中
- 使用 pnpm install 安装好依赖
- 点击项目 /src 目录中的任意文件
- 点击编辑器上方点击运行选择需要运行的环境
功能示例
静态资源处理
// 使用远程静态资源
// import { useAssets } from './utils/assets/remote'// 使用本地静态资源
import { useAssets } from './utils/assets/local'// 全局挂载
app.config.globalProperties.$assets = useAssets// template中使用
// <img :src="$assets('/temp.png')" />
全局主题色定制
由 unocss-preset-shades 提供支持
<!-- 设置文本色为主题色色调为 500 -->
<div class="text-primary-500"></div>
<!-- 设置背景色为主题色色调为 500 -->
<div class="bg-primary-500"></div>
<!-- 设置边框色为主题色色调为 500 -->
<div class="border border-primary-500"></div>
<!-- 更多使用方式请参阅 https://tailwindcss.com/docs -->
请求后端数据
详细使用请参阅 uni-network
import request from '@/utils/request/index.js'// GET
request.get('/mock',{ id: 'mock-id' },{/* More option */}
)// POST
request.post('/mock',{ id: 'mock-id' },{/* More option */}
)// Upload
request.upload({url: '/mock',dataType: 'json',headers: {'content-type': 'multipart/form-data',},
})// Common
request({method: 'post',url: '/mock',data: {id: 'mock-id',},headers: {'content-type': 'application/json',},
})// 扩展方法// 继承于 request.post,请求头默认添加 'Content-Type': 'multipart/form-data'
request.form('/mock',{ id: 'mock-id' },{/* More option */}
)// 继承于 request.post,请求头默认添加 'Content-Type': 'application/x-www-form-urlencoded'
request.query('/mock',{ id: 'mock-id' },{/* More option */}
)
路由间功能跳转
// 跳转页面
const methods = {routerDemo() {this.$Router.push({path: '/login',query: {id: 'id',},})// 获取页面参数this.$Route.query.id// 关闭当前页面跳转到某个页面this.$Router.replace('/login')// 关闭所有打开的页面跳转到某个页面this.$Router.replaceAll('/login')},
}// 为路由设置别名
// pages.config.js 中
const aliasConfig = {path: 'pages/login/index',// 通过添加 aliasPath 字段aliasPath: '/login',
}
使用路由守卫
位于 router/guards 中
import store from '@/store/index.js'const homePath = '/pages/index/index'
const loginPath = '/pages/login/index'const whiteList = [loginPath]export default (router) => {const userStore = store.useUserStore()const loginRoute = to => ({path: loginPath,navType: 'reLaunch',force: true,query: {redirect: {path: to.path,query: to.query,},},})router.beforeEach((to, from, next) => {// console.log('permission.beforeEach.to', to)// console.log('permission.beforeEach.from', from)const token = userStore.tokenconst userId = userStore.userIdconsole.log('token', token)console.log('userId', userId)if (token) {if (to.path === loginPath) {next(homePath)}else if (userId) {next()}else {userStore.getUserInfo().then(() => {next()}).catch((error) => {console.warn(error)userStore.logout({ silenced: true })next(loginRoute(to))})}}else if (whiteList.includes(to.path)) {next()}else {next(loginRoute(to))}})router.afterEach(() => {})
}
使用基于路由的中间件
pages.config.js 中
// 使用名为 realname 的中间件
const pageConfig = {path: '/pages/user/index',aliasPath: '/user',meta: {middleware: ['realname'],},
}
定义中间件
router/guards/index.js 中
// 使用 defineMiddleware 定义并包装为中间件
import realname from './realname/index.js'
import { defineMiddleware } from '$uni-router/middleware'export default (app, router) => {// 使用 defineMiddleware 定义了路由中间件defineMiddleware(realname, { router, app })
}
编写路由中间件代码
router/guards/realname/index.js 中
import store from '@/store/index.js'
import { useDialog, useToast } from '@/utils/modals'export default (router) => {const userStore = store.useUserStore()router.beforeEach((to, from, next) => {console.log('realname.beforeEach.to', to)console.log('realname.beforeEach.from', from)const realStatus = userStore.userInfo.realStatusswitch (realStatus) {case 3:next()breakcase 2:useToast('实名审核中, 请稍后再试').then(() => {next(false)})breakcase 4:useDialog(`${userStore.userInfo.auditResult || '提交的实名信息不符'}`, {title: '实名失败',showCancelButton: true,confirmText: '重新认证',}).then(() => {next({ path: '/pages/realname/index' })}).catch(() => {next(false)})breakdefault:useDialog('请先进行实名认证', { showCancelButton: true }).then(() => {next({ path: '/pages/realname/index' })}).catch(() => {next(false)})break}})// router.afterEach(() => {})
}
主要使用的包
- vitejs
- uniapp
- pinia
- uview-plus
- uni-ui
- @uni-helper/uni-network
- uniapp-router-next
- z-paging
- unocss
- unocss-applet
常见问题
无法正常安装依赖/无法启动
删除 pnpm-lock.yaml / yarn.lock / package-lock.json 文件后重新安装依赖
sass提示
Deprecation Warning: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
More info and automated migrator: https://sass-lang.com/d/import
解决:将sass版本换为稳定版 "sass": "1.77.6"