# Jun-uni **Repository Path**: ljb2458/jun-uni ## Basic Information - **Project Name**: Jun-uni - **Description**: 一个使用 Uniapp + Vue3 + TypeScript + uv-ui | wd-ui + Vite 打造的开箱即用框架,封装了CoRequsetList CoTabsFor 等特色组件,所有组件均拥有良好的 TypeScript 类型支持 - **Primary Language**: TypeScript - **License**: MIT - **Default Branch**: master - **Homepage**: https://gitee.com/ljb2458/jun-uni - **GVP Project**: No ## Statistics - **Stars**: 12 - **Forks**: 1 - **Created**: 2023-07-03 - **Last Updated**: 2025-09-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Jun-uni ## 项目介绍 > ⭐`Jun-uni` 是一个由个人开发者 `Juncoder` 积累四年开发经验打造的适用中小型公司一般开发情况的 uniapp 开箱即用高效开发框架。 > ⭐`Jun-uni` 的诞生是为了解决 `Uniapp` 多端兼容麻烦、使用 `HBuilder X` 开发体验一般、对 `TypeScript` 支持不好的问题,旨在优化开发体验、减少兼容代码。 > ⭐ 该框架使用 `Uniapp` `Vue3` `TypeScript` `Pinia` `luchRequest` `Vite` `uv-view` 打造。 > 因此在使用此框架前,我推荐你先学习或了解 `Uniapp` `Vue3` `TypeScript` `Pinia` `Axios(luchRequest)` > 该框架使用的 `node` 版本为 `v22.13.1` 为了减少运行时所带来的错误,请尽可能使用与 `v22.13.1` 相近的版本。 ### 框架解决了以下开发痛点 - ⭐`pages.json` 配置麻烦、不便查阅? - 使用 `vite` 插件 `generatePagesJson` 自动生成 `pages.json` 配置文件。 - 配置项直接写在当前 `vue` 文件中,一目了然。 - 文件目录就是小程序分包方式,非常好理解。 - ⭐ 习惯 `vs code` 开发,可在 vs code 中 `uniapp` 原生组件总是没代码提示? - 每个 uniapp 原生组件都有类型标注,无需担心代码提示问题。 - ⭐ 实现 `tabs` 选项卡,高度总是问题? - 使用组件 `CoTabsFor` 传入一个数组,定义一个插槽可以轻松实现自动高度的 tabs 选项卡。 - ⭐ 分页列表处理麻烦,总是涉及数组操作? - 使用组件 `CoRequestList` ,仅需传入一个使用适配器包装后的 `api` 方法 加上一个 `item` 插槽,即可加载分页数据。 - ⭐ 自定义导航栏注册麻烦,担心与原生导航栏冲突,计算页面高度时还需要考虑有没有开启自定义导航? - 在组件 `CoPageView` 中根据 `pages.json` 对应配置,**自动决定要不要注册自定义导航栏**。 - 在组件 `CoPageView` 为您计算好导航栏高度和页面可用高度,生成 css 样式 `--layout-navbar-height` 和 `--layout-page-height`。 - ⭐ 写在底部的固定按钮,忘记计算底部安全区、忘记写占位符,导致页面最底部元素被按钮遮盖,无法完整的查看? - 在组件 `CoPageView` 中提供了 `fixedBottom` 插槽,计算安全区并在页面生成占位元素的同时,将你的元素定位到页面最底部。 - ⭐`uni.request` 不够好用? - `/utils/httpRequest` 基于 `luchRequest` 进行二次封装,神似 `Axios` 有请求拦截器、响应拦截器、自动提示等。 - ⭐ 路由跳转、路由传参需要自己拼接字符串? - `/utils/router` 二次封装路由跳转,自动拼接 `Query` 参数。 - ⭐ 找不到对 `TypeScript` 支持良好的 `uniapp` 框架? - `Jun-uni` 框架中的所有 方法、组件、示例代码、包括 `uniapp` 的原生组件,均有良好的 `TypeScript` 支持 - ⭐ 微信小程序组件总是多渲染一层组件盒,影响样式编写? - 每个公共组件都不会有多余的组件盒,减少平台差异。 - `Jun-uni` 框架中的所有 方法、组件、示例代码、包括 `uniapp` 的原生组件,均有良好的 `TypeScript` 支持 - 开启了过多相同的循环定时器,造成性能浪费、忘记关闭循环定时器? - 使用 `/hooks/toolsHooks` 中的 `useInterval` 同样间隔时间的循环定时器只会被开启一次。 - 全局状态管理 `store(pinia、vuex)` 数据持久化麻烦? - `pinia + mp-storage + pinia-plugin-persistedstate` 简单而优雅的解决问题。 - `picker` 用户体验不好,市面上又缺少好用的级联选择器? - `CoCascader 级联选择器组件` 动画流畅,使用简单。 - 分栏编写样式麻烦、样式名难想、`tailwindcss` 体积太大、不好定制、且对小程序支持不好? - 支持 `unocss` + `unocss-preset-uni` 来支持小程序,使用官方插件获得代码提示。 - 主题不好定制,定制好自己的颜色还要定制 UI 框架的颜色? - src/constants/unocss 专门的配置文件,一键配置你的项目主题。 ## 预览 | 微信小程序请扫这里 | App 请点击这里下载 | | ------------------------------------------------------------ | ----------------------------- | | | [安卓下载链接](./README/apk/) | ## 开始 ### 拉取 ```bash git clone https://gitee.com/ljb2458/jun-uni.git ``` - 使用 `VS code` 打开项目。 - 接受弹出的推荐插件。 - 如果你需要我的更新,推荐**新建分支**进行开发,并定期**合并代码**。 ### 首次启动 - 安装依赖 ```shell pnpm i ``` - 启动 ```shell //网页 pnpm run dev:h5 //微信小程序 pnpm run dev:mp-weixin ``` - 然后根据控制台提示进行操作。 - 或在 `HBuilder X` 中启动项目。 ## 习惯与环境 **使用该框架,我推荐你使用 `vs code` 编译器并接受安装我为你推荐的 vscode 插件** —— 在首次进入项目时编译器会提示你安装我所推荐的插件。你也可以在 .vscode/extensions.json 以此复制 recommendations 的每一项搜索并安装。 **使用该框架,我推荐你添加以下代码片段。** `vs code` 左下角小齿轮=>代码片段=>选择 `vue3-module.code-snippets` ```json { //其他代码片段... "uniapp页面": { "prefix": "uni-page", "body": [ "", "{", " \"navigationBarTitleText\": \"${1:新页面}\",", " \"enablePullDownRefresh\": false,", " \"navigationStyle\": \"custom\",", " \"navigationBarTextStyle\": \"white\"", "}", "", "", "", "", "", "", "", "" ], "description": "uniapp 页面" } } ``` `vs code` 左下角小齿轮=>代码片段=>选择 `typescript.json` ```json { //其他代码片段... "pinia仓库": { "prefix": "pinia-store", "body": [ "import { defineStore } from \"pinia\";", "//import { localStorage } from \"mp-storage\";", "", "export const use$1Store = defineStore(\"$1Store\", {", " //*全局仓库", " state,", " //*全局函数", " actions: {},", " //*计算属性", " getters: {},", " //*仓库数据缓存", " persist: [", " {", " key: \"$1Store\",", " storage: localStorage, //指定储存位置", " },", " ],", "});", "/**state类型定义 */", "export namespace $1Store {", " export interface Store {}", "}", "/**初始化pinia */", "function state(): $1Store.Store {", " return {", " };", "}", "" ], "description": "pinia仓库" }, "api接口模板": { "prefix": "api-template", "body": [ "/**${3:模板接口} */", "export async function api${2:Template}(", " data: Api${2:Template}.Req", "): Promise> {", " const res = await defHttp.post>(\"${1:记得替换我}\", data, {", " custom: {", " failMessage: true,", " },", " });", " return res;", "}", "", "/**${3:模板接口} */", "export namespace Api${2:Template} {", " export interface Req {}", " export interface Res {}", "}", "" ], "description": "api接口模板" } } ``` 使用这个代码模板可以快速生成改框架常用的代码块。 ## 文件目录 ``` vite-plugins | //存放本地 vite 插件。 |-generatePagesJson |-index.ts //用于生成pages.json配置文件; src |-layout | //存放在 CoPageView 中注册的组件,一般会在全部页面使用。 |-style | //存放预设、公共、scss 文件。 |-components|-common //存放公用组件,一般为自创组件。 |-group //存放组合组件,一般为多个组件的纯粹组合,非新组件。 |-rewrite //存放二次封装的组件,一般改动较小,基本保持原组件的概念。 |-native //存放一般只有这个项目才能用到的公共业务组件。 |-constants | //存放一些常量,包括发布订阅所用的Key等。 |-init.ts //项目加载、App.vue 初始化、登录完成 时干的事。 types |-dts | //全局配置、组件、等ts存放目录 |-modult.d.ts //全局模块声明 |-typeFunction.d.ts //自定义ts类型生成与转换方法 |-components.d.ts //全局组件ts声明目录 |-auto-import | //自动生成ts类型存放目录 ``` ## 对接后端接口 1. 设置接口地址及后缀 1. 在 `/.env.development、/.env.production` 中修改 `VITE_API_URL 接口请求地址`,**⚠ 注 ❗ 如果为空请将该行注释。没有值的 `env` 配置文件 将会造成 `h5` 无法正常启动的诡异问题** ```env # 请求接口地址 VITE_API_URL=https://你的api接口地址 # 其它配置... ``` 2. 重启项目。 2. 修改示例 `token` 的传递方式 1. 在 `/src/api/index.ts` 中找到 `defHttp.interceptors.request.use` 修改其中的请求配置。 ```ts //请求拦截器,在这里设置 token defHttp.interceptors.request.use((config) => { const userStore = useUserStore(); config.header = { ...config.header, token: userStore.token, }; return config; }); ``` 3. 修改返回结果的类型 1. 在 `/src/api/index.ts` 中找到 `export namespace Api` 修改其中的类型定义。 ```ts /**请求res类型 */ export namespace Api { export interface SuccessRes { code: 200; message: string; time: Date; type: string; isSuccess: true; result: T; } export interface FailRes { code: number; message: string; time: Date; type: string; isSuccess: false; result?: T; } export type Res = SuccessRes | FailRes; } ``` 4. 修改示例 `isSuccess`、`giveMsg`、`giveErrMsg` 方法 1. 在 `/src/api/index.ts` 中找到 `export const defHttp = createHttpRequest` 方法,修改传入的两个个函数为实际数据。 ```ts export const defHttp = createHttpRequest( { isSuccess(res) { return res?.data?.code === 200; }, giveMsg(res) { return res?.data?.message; }, giveErrMsg(error) { return error?.errMsg; }, }, { baseURL, } ); ``` 5. 在 `/src/api/userinfo` 中复制粘贴或直接修改一个接口并调用。 ## 路由鉴权 在 src/init.ts 中有一个 routerCheck 方法,在这里编写路由鉴权的逻辑。让后在 .env.development 中将 VITE_REQUIRED_LOGIN 设为 1 ## 自动生成 pages.json(vite 插件) 在 `vite.config.ts` 中需改 `generatePagesJson` 中的相关配置 ```ts //其它代码... generatePagesJson({ /**输出文件 */ outFile: "./src/pages.json", /**第一个页面 */ firstPage: "./src/pages/tabbar/home/home.vue", /**主包文件夹 */ mainPackageDir: "./src/pages/tabbar/", /**页面所在目录 */ pagesDir: "./src/pages/", }), ``` ### 页面生成规则 - `generatePagesJson` 会自动将 `/src/pages` 下的每一个目录当作一个分包生成,而`mainPackageDir` 所指向的文件夹将会被放到主包配置内。 - `generatePagesJson` 插件会读取 `pages.json` 下的配置对象,并替换 `pages` 和 `subPackages` 这两项配置,你可以放心的修改除这两项配置以外的配置。 ## 选型解释 - 为什么不使用 `vite-plugin-uni-pages` 来实现自动生成 `pages.json`? - `vite-plugin-uni-pages` 从大体上确实能实现该功能,但 `vite-plugin-uni-pages` 不符合规范大于配置的设计理念,在使用了 `vite-plugin-uni-pages` 后,任需要手动配置分包规则,因此,作者自己写了一个本地 `vite` 插件。 ## 旧版本 该框架已经从自写 `原子化 css` 迁移至 `unocss` 不再建议使用自写 `原子化 css` 进行开发,旧版本的,可以在 src/styles/index.scss 与同路径下的 effects.scss 中解开相应注释继续使用。 该框架已转到 `wot-design-uni` 框架,并打算以后将 `wot-design-uni` 作为主力框架,建议使用 `wot-design-uni` 作为 UI 框架进行开发,已有的组件会进行兼容。