feat: 把 docs 仓库移动到本仓库
196
docs/base/1-introduction.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# 简介
|
||||
|
||||
<div class="md-center" style="margin-top: 20px;">
|
||||
|
||||
[](https://github.com/codercup/unibest)
|
||||
[](https://github.com/feige996/unibest)
|
||||
[](https://gitee.com/codercup/unibest)
|
||||

|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
> 上面前 2 个 `star` 分别是旧仓库 `codercup` 和新仓库 `feige996` 的 `star` 数。
|
||||
|
||||
`unibest` 是最好的 `uniapp` 开发框架,由 `uniapp` + `Vue3` + `Ts` + `Vite5` + `UnoCss` + `VSCode`(可选 `webstorm`) + `uni插件`+ `wot-ui`(可选其他 UI 库)构建,集成了多种工具和技术,使用了最新的前端技术栈,无需依靠 `HBuilderX`,通过命令行方式即可运行 `web`、`小程序` 和 `App`。(注:`App` 还是需要 `HBuilderX`)
|
||||
|
||||
`unibest` 内置了 `约定式路由`、`layout布局`、`请求封装`、`请求拦截`、`登录拦截`、`UnoCSS`、`i18n多语言` 等基础功能,提供了 `代码提示`、`自动格式化`、`统一配置`、`代码片段` 等辅助功能,让你编写 `uniapp` 拥有 `best` 体验 ( `unibest 的由来`)。
|
||||
|
||||
> `unibest` 目前支持 `H5`、`小程序` 和 `App`。
|
||||
|
||||
## ⭐ Star History
|
||||
|
||||
Github Star History 实时地址:[https://star-history.com/#codercup/unibest&Date](https://star-history.com/#codercup/unibest&Date) 。
|
||||
|
||||
[](https://star-history.com/#codercup/unibest&Date)
|
||||
|
||||
与同类型模板对比,如下图,红色的为 `unibest`,后来居上,遥遥领先。
|
||||
|
||||
:::details
|
||||
|
||||
[](https://star-history.com/#codercup/unibest&Ares-Chang/uni-vitesse&uni-helper/vitesse-uni-app&Date)
|
||||
|
||||
同类模板对比实时地址:[https://star-history.com/#codercup/unibest&Ares-Chang/uni-vitesse&uni-helper/vitesse-uni-app&Date](https://star-history.com/#codercup/unibest&Ares-Chang/uni-vitesse&uni-helper/vitesse-uni-app&Date)
|
||||
:::
|
||||
|
||||
## 🗂 生成过程
|
||||
|
||||
`unibest` 由最初始的官方 cli 脚手架模板生成,执行的命令如下:
|
||||
|
||||
```sh
|
||||
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
|
||||
```
|
||||
|
||||
`uniapp` 官方链接:[点击跳转 - quickstart-cli](https://uniapp.dcloud.net.cn/quickstart-cli.html)
|
||||
|
||||
在官方生成的项目基础上,增加了如下内容:
|
||||
|
||||
- 前端基础配置六件套
|
||||
- prettier
|
||||
- eslint
|
||||
- stylelint
|
||||
- husky
|
||||
- lint-staged
|
||||
- commitlint
|
||||
- UnoCSS
|
||||
- UnoCSS Icons
|
||||
- Uni 插件
|
||||
- vite-plugin-uni-pages
|
||||
- vite-plugin-uni-layouts
|
||||
- vite-plugin-uni-manifest
|
||||
- vite-plugin-uni-platform
|
||||
- UI 库(默认 `wot-ui`,支持替换其他 `UI库`)
|
||||
- pinia + pinia-plugin-persistedstate
|
||||
- 通用功能
|
||||
- 请求封装
|
||||
- 请求拦截
|
||||
- 路由拦截
|
||||
|
||||
## ✨ 特性
|
||||
|
||||
- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [esbuild](https://github.com/evanw/esbuild) - 就是快!
|
||||
|
||||
- 🔥 最新语法 - `<script lang="ts" setup>` 语法
|
||||
|
||||
- 🎨 [UnoCSS](https://unocss.dev/) - 高性能且极具灵活性的即时原子化 CSS 引擎
|
||||
|
||||
- 😃 [UnoCSS Icons](https://unocss.dev/presets/icons) & [icones](https://icones.js.org/) - 海量图标供你选择
|
||||
|
||||
- 🍍 [pinia](https://pinia.vuejs.org/) & [pinia-plugin-persistedstate](https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/) - 全端适配的全局数据管理
|
||||
|
||||
- 🗂 `uni.request` 请求封装 - 一键引入,快捷使用
|
||||
|
||||
- 📦 `路由拦截` 基础封装,支持扩展,快捷使用,拒绝黑盒
|
||||
|
||||
- 📥 [API 自动加载](https://github.com/antfu/unplugin-auto-import) - 直接使用 Composition API 无需引入
|
||||
|
||||
- 🎉 `v3` Code Snippets 加快你的页面生成
|
||||
|
||||
- 🦾 `Pritter` & `ESLint` & `Stylelint` & `husky` & `lint-staged` + `commitlint` - 保证代码质量
|
||||
|
||||
- 🌈 `TypeScript` 加持,同时又兼容 `js` ,同时满足不同人群
|
||||
|
||||
- 💡 `ES6 import` 自动排序,`css 属性` 自动排序,增强编码一致性
|
||||
|
||||
- 🖥 `多环境` 配置分开,想则怎么配置就怎么配置
|
||||
|
||||
## 📦 目录结构
|
||||
|
||||
通过 `tree -I node_modules -I dist -I .git -a > tree.md` 命令生成。
|
||||
|
||||
```txt
|
||||
.
|
||||
├── .editorconfig
|
||||
├── .eslintignore
|
||||
├── .eslintrc-auto-import.json
|
||||
├── .eslintrc.cjs
|
||||
├── .gitignore
|
||||
├── .husky
|
||||
├── .npmrc
|
||||
├── .prettierignore
|
||||
├── .prettierrc.cjs
|
||||
├── .stylelintignore
|
||||
├── .stylelintrc.cjs
|
||||
├── .vscode
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
├── commitlint.config.cjs
|
||||
├── env
|
||||
│ ├── .env
|
||||
│ ├── .env.development
|
||||
│ ├── .env.production
|
||||
│ └── .env.test
|
||||
├── favicon.ico
|
||||
├── index.html
|
||||
├── manifest.config.ts
|
||||
├── package.json
|
||||
├── pages.config.ts
|
||||
├── src
|
||||
│ ├── App.vue
|
||||
│ ├── components
|
||||
│ │ └── .gitkeep
|
||||
│ ├── env.d.ts
|
||||
│ ├── hooks
|
||||
│ │ ├── .gitkeep
|
||||
│ │ ├── useRequest.ts
|
||||
│ │ └── useUpload.ts
|
||||
│ ├── interceptors
|
||||
│ │ ├── index.ts
|
||||
│ │ ├── prototype.ts
|
||||
│ │ ├── request.ts
|
||||
│ │ └── route.ts
|
||||
│ ├── layouts
|
||||
│ │ ├── default.vue
|
||||
│ │ └── demo.vue
|
||||
│ ├── main.ts
|
||||
│ ├── manifest.json
|
||||
│ ├── pages
|
||||
│ │ ├── about
|
||||
│ │ │ ├── about.vue
|
||||
│ │ │ └── components
|
||||
│ │ │ ├── request.vue
|
||||
│ │ │ └── upload.vue
|
||||
│ │ └── index
|
||||
│ │ └── index.vue
|
||||
│ ├── pages-sub
|
||||
│ │ └── demo
|
||||
│ │ └── index.vue
|
||||
│ ├── pages.json
|
||||
│ ├── service
|
||||
│ │ └── index
|
||||
│ │ └── foo.ts
|
||||
│ ├── static
|
||||
│ │ ├── images
|
||||
│ │ │ └── .gitkeep
|
||||
│ │ ├── logo.svg
|
||||
│ │ └── tabbar
|
||||
│ │ ├── example.png
|
||||
│ │ ├── exampleHL.png
|
||||
│ │ ├── home.png
|
||||
│ │ ├── homeHL.png
|
||||
│ │ ├── personal.png
|
||||
│ │ └── personalHL.png
|
||||
│ ├── store
|
||||
│ │ ├── index.ts
|
||||
│ │ └── user.ts
|
||||
│ ├── style
|
||||
│ │ └── index.scss
|
||||
│ ├── types
|
||||
│ │ ├── auto-import.d.ts
|
||||
│ │ ├── global.d.ts
|
||||
│ │ ├── shims-uni.d.ts
|
||||
│ │ └── uni-pages.d.ts
|
||||
│ ├── typings.ts
|
||||
│ ├── uni.scss
|
||||
│ ├── uni_modules
|
||||
│ │ └── .gitkeep
|
||||
│ └── utils
|
||||
│ ├── http.ts
|
||||
│ ├── index.ts
|
||||
│ └── platform.ts
|
||||
├── tsconfig.json
|
||||
├── uni-pages.d.ts
|
||||
├── uno.config.ts
|
||||
└── vite.config.ts
|
||||
```
|
||||
163
docs/base/10-i18n.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 多语言篇
|
||||
|
||||
`多语言` 是一个常见的需求, `unibest` 专门开发了一个 `i18n`模板,可以直接生成 `多语言模板项目`。
|
||||
|
||||
```sh
|
||||
pnpm create unibest my-project -t i18n
|
||||
```
|
||||
|
||||
`vue组件` 里面使用方式如下:
|
||||
|
||||
```html
|
||||
<view class="m-4">{{ $t('app.name') }}</view>
|
||||
```
|
||||
|
||||
`非vue组件` 里面怎么使用呢?比如 `ts` 文件。
|
||||
|
||||
这时需要用到作者编写的 `translate` 函数,使用方式如下:
|
||||
|
||||
```ts
|
||||
import { translate as t } from '@/locale/index'
|
||||
|
||||
/** 非vue 文件使用 i18n */
|
||||
export const testI18n = () => {
|
||||
console.log(t('app.name'))
|
||||
// 下面同样生效
|
||||
uni.showModal({
|
||||
title: 'i18n 测试',
|
||||
content: t('app.name'),
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
上面基本的使用都是没问题的,但是传递参数时,只有 `H5端` 生效,`其他端` 是不生效的,代码如下:
|
||||
|
||||
```html
|
||||
<view class="m-4">{{ $t('weight', { heavy: 100 }) }}</view>
|
||||
```
|
||||
|
||||
`H5端` 效果如下,正常显示:
|
||||
|
||||

|
||||
|
||||
`非H5端` 效果如下,异常显示:
|
||||
|
||||

|
||||
|
||||
下面我们就来处理这个问题。
|
||||
|
||||
## 多语言传参
|
||||
|
||||
上面提到 `vue-i18n` 在 `非H5端` 传参时显示异常,那我们就来处理一下,主要方式就是通过 `正则` 替换 `多语言字符串`。
|
||||
|
||||
编写一个函数 `formatI18n`,如下:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* formatI18n('我是{name},身高{detail.height},体重{detail.weight}',{name:'张三',detail:{height:178,weight:'75kg'}})
|
||||
* 暂不支持数组
|
||||
* @param template 多语言模板字符串,eg: `我是{name}`
|
||||
* @param obj 需要传递的对象,里面的key与多语言字符串对应,eg: `{name:'菲鸽'}`
|
||||
* @returns
|
||||
*/
|
||||
export function formatI18n(template, data) {
|
||||
const match = /\{(.*?)\}/g.exec(template)
|
||||
if (match) {
|
||||
const variableList = match[0].replace('{', '').replace('}', '').split('.')
|
||||
let result = data
|
||||
for (let i = 0; i < variableList.length; i++) {
|
||||
result = result[variableList[i]] || ''
|
||||
}
|
||||
return formatStr(template.replace(match[0], result), data)
|
||||
} else {
|
||||
return template
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`vue组件` 里面使用方式如下:
|
||||
|
||||
```html
|
||||
<view class="m-4">{{ formatI18n(translate('introduction'), user) }}</view>
|
||||
```
|
||||
|
||||
用到的函数引入如下:
|
||||
|
||||
```js
|
||||
import { formatI18n, translate } from '@/locale/index'
|
||||
```
|
||||
|
||||
对应的 en.json 文件如下:
|
||||
|
||||
```json
|
||||
{ "introduction": "I am {name},height:{detail.height},weight:{detail.weight}" }
|
||||
```
|
||||
|
||||
`user` 对象如下:
|
||||
|
||||
```js
|
||||
{name:'张三',detail:{height:178,weight:'75kg'}}
|
||||
```
|
||||
|
||||
这样,在 `H5端` 和 `非H5端` 都能正常显示,如下:
|
||||
|
||||

|
||||
|
||||
very good !
|
||||
|
||||
## 导航栏标题
|
||||
|
||||
目前发现 `导航栏标题` 在 `小程序端` 不会跟随多语言切换而切换,比如说刚开始是中文,切换成英文后,页面内容都变成英文了,标题栏还是中文。
|
||||
|
||||
> `App端` 说明:`App模拟器`,以我的 `mac电脑` `ios模拟器` 来说,是正常的,可以直接切换,多语言也是生效的。
|
||||
>
|
||||
> 但是 `安卓真机` 会出现`切换多语言后,自动重启,然后界面多语言是生效的`。
|
||||
>
|
||||
> 既然 `App 正常`,这里主要说 `小程序端` 不正常的处理。
|
||||
|
||||
`小程序端` 需要使用 `uni.setNavigationBarTitle` 来手动处理,`API` 使用如下:
|
||||
|
||||
```js
|
||||
uni.setNavigationBarTitle({
|
||||
title: '新的标题',
|
||||
})
|
||||
```
|
||||
|
||||
结合 `translate` 函数,则:
|
||||
|
||||
```js
|
||||
uni.setNavigationBarTitle({
|
||||
title: translate('app.name'),
|
||||
})
|
||||
```
|
||||
|
||||
可以满足大部分场景。
|
||||
|
||||
## tabbar 标题
|
||||
|
||||
同 `导航栏标题`。
|
||||
|
||||
## App 端视频
|
||||
|
||||
这里给出 `2` 个 `App端` 的视频,加深开发者的认识和印象。
|
||||
|
||||
:::details
|
||||
|
||||
### `ios模拟器` 多语言直接就是生效的
|
||||
|
||||
<video src="./assets/10-ios.mp4" controls="controls" width="100%" height="100%"></video>
|
||||
|
||||
### `安卓真机` 会自动重启,重启后界面多语言是生效的
|
||||
|
||||
<video src="./assets/10-android.mp4" controls="controls" width="100%" height="100%"></video>
|
||||
:::
|
||||
|
||||
## 总结
|
||||
|
||||
本文介绍了 `unibest` 里面使用 `多语言` 的基本方式,还处理了 `3` 个多端异常的问题:
|
||||
|
||||
- `多语言传参` 不生效 BUG
|
||||
- `导航栏标题` 切换多语言不生效 BUG
|
||||
- `tabbar标题` 切换多语言不生效 BUG
|
||||
|
||||
全文完~
|
||||
111
docs/base/11-build.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 运行发布
|
||||
|
||||
## 运行
|
||||
|
||||
- `h5 平台`: `pnpm dev:h5`( 或者简单点 `pnpm dev` ),然后浏览器打开 `http://localhost:9000/`。
|
||||
- `wx 小程序`:`pnpm dev:mp-weixin`,然后打开微信开发者工具,导入本地文件夹,选择本项目的 `dist/dev/mp-weixin` 文件。
|
||||
- 
|
||||
|
||||
- `APP 平台`:`pnpm dev:app`,然后打开 `HBuilderX`,导入刚刚生成的 `dist/dev/app` 文件夹,选择运行到 `模拟器`( `开发时优先使用` ),或者 `运行到安卓/ios 基座` (真机调试时使用) 。
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
> 如果需要配置其他模拟器,可以参考:[安装模拟器](https://uniapp.dcloud.net.cn/tutorial/run/installSimulator.html)
|
||||
|
||||
> 这样操作的话,开发时都会有热更新,开发体验很爽!
|
||||
|
||||
## 发布
|
||||
|
||||
- `h5 平台`: `pnpm build:h5`,打包后的文件在 `dist/build/h5`,可以放到 web 服务器,如 nginx 运行。如果最终不是放在根目录,可以在 `manifest.config.ts` 文件的 `h5.router.base` 属性进行修改。
|
||||
- `wx 小程序`:`pnpm build:mp-weixin`,打包后的文件在 `dist/build/mp-weixin`,然后通过微信开发者工具导入,并点击右上角的“上传”按钮进行上传。
|
||||
- `APP 平台`:`pnpm build:app`,然后打开 `HBuilderX`,导入刚刚生成的 `dist/build/app` 文件夹,选择 `发行` - `原生APP-云打包`。
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
> 熟悉原生 APP 开发的开发者也可以使用 `原生APP-本地打包`。
|
||||
|
||||
## APP 打包注意事项(上)
|
||||
|
||||
很多开发者发现打包失败,或者打包白屏,这里简单说明一下。
|
||||
|
||||
- 1. 重新获取自己的 `AppId`
|
||||
|
||||

|
||||
|
||||
- 2. 根据上面获取到的 `AppId` 修改 `env/.env` 文件的 `VITE_UNI_APPID` 字段
|
||||
|
||||

|
||||
|
||||
- 3. (可选)云打包如果有出现解析时出问题的,把 `minSdkVersion` 版本改低一点就好了,比如 `21`。(最低 `21`,不能低于 `21`;我模板里面设置的是 `30`)。
|
||||
|
||||

|
||||
|
||||
## APP 打包注意事项 (下)
|
||||
|
||||
### `uni-app SDK` 版本
|
||||
|
||||
> 特别备注:`2024-05-03`,新的 `base` 模板的 `uni-app SDK` 版本已经升级到 `4.14` 了。
|
||||
>
|
||||
> 
|
||||
|
||||
`2024-04-14`,新的 `base` 模板的 `uni-app SDK` 版本已经升级到 `4.08` ,记得更新您的 `HBuilderx` 版本。
|
||||
|
||||
`"@dcloudio/uni-app": "3.0.0-4000820240401001"` 表示 `uni-app` 为 `3.0.0` 版本,对应的 `HBuilderx` 版本为 `4.08`,后面的 `20240401001` 是发布日期。
|
||||
|
||||
> `40008` 第一个数字 `4` 表示主要版本,后面每 `2` 位数为一组,所以代表 `4.0.8`。
|
||||
>
|
||||
> 类似的,`30812` 代表 `3.8.12` 版本,`30909` 代表 `3.9.9` 版本。
|
||||
>
|
||||
> 另外,从 `3.99` 开始,后面 2 个小版本合并书写,于是 `3.9.9` 变成 `3.99`,`4.0.8` 变成 `4.08`。
|
||||
|
||||
`unibest` 历史用过的 `@dcloudio/uni-app` 版本:
|
||||
|
||||
```text
|
||||
"@dcloudio/uni-app": "3.0.0-3081220230817001", => 3.8.12
|
||||
"@dcloudio/uni-app": "3.0.0-3090920231225001", => 3.99
|
||||
"@dcloudio/uni-app": "3.0.0-4000820240401001", => 4.08
|
||||
"@dcloudio/uni-app": "3.0.0-4010420240430001", => 4.14
|
||||
```
|
||||
|
||||

|
||||
|
||||
### `uni-app SDK` 版本匹配 `HBuilderX`
|
||||
|
||||
> 温馨提示:下面的部分是使用 `uni-app` 版本为 `3.8.12` 时写的文档,适当参考~
|
||||
|
||||
本模板使用的是 `3.8.12` 的库版本(`"@dcloudio/uni-app": "3.0.0-3081220230817001",`),所以尽量使用 `3.8.12` 版本的 `HBuilderX` 来打包,否则可能有未知的风险,出现情况如下图。
|
||||
|
||||
> 原来的图不见了,重新补了一张。
|
||||
|
||||

|
||||
|
||||
上图表示您的 `HBuilderX` 版本是 `4.08`,但是代码 `uni-app SDK` (即 `"@dcloudio/uni-app": "3.0.0-4010420240430001"` ) 是 `4.14`,版本不匹配。
|
||||
|
||||
- 点击 `ignore`(忽略) 后若可以正常使用,那就不用管。(可选添加如下配置)
|
||||
|
||||
```json
|
||||
"app-plus" : { "compatible": { "ignoreVersion": true } }
|
||||
```
|
||||
|
||||
- 如果出现白屏啥的,请更新您的 `HBuilderX` 到 `uni-app SDK` 相同版本(这里是 `4.14` )。
|
||||
|
||||
### 多个 `HBuilderX` 版本安装
|
||||
|
||||
> 温馨提示:下面的部分是使用 `uni-app` 版本为 `3.8.12` 时写的文档,适当参考~
|
||||
|
||||
`MAC` 可以安装多个版本的软件,如下图我安装了 `3.8.12` (3.8.12.20230817) 和最新的 `3.99` (3.99.2023122611) 两个版本,平时的项目使用 `3.99`, 打包 `unibest` 的时候使用 `3.8.12`。
|
||||
|
||||

|
||||
|
||||
> `window` 系统也可以同时安装多个 `HBuilderX` 版本,安装时选择安装到不同目录下即可。
|
||||
|
||||
## 总结
|
||||
|
||||
本文描述了多端的运行和发布,希望对您有帮助。
|
||||
|
||||
全文完~
|
||||
89
docs/base/12-env.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# 环境变量
|
||||
|
||||
主要介绍 `vite` 环境变量和 `uni` 环境变量。
|
||||
|
||||
## `vite` 环境变量
|
||||
|
||||
`Vite` 在一个特殊的 `import.meta.env` 对象上暴露环境变量。环境变量定义在 `.env` 文件里。
|
||||
|
||||
### .env 文件
|
||||
|
||||
创建环境文件:
|
||||
|
||||
```yml
|
||||
.env # 所有情况下都会加载
|
||||
.env.local # 所有情况下都会加载,但会被 git 忽略
|
||||
.env.[mode] # 只在指定模式下加载
|
||||
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略
|
||||
|
||||
# 注意 .env.local 无法覆盖 .env.[mode]
|
||||
```
|
||||
|
||||
环境文件只包含环境变量的 `键值对` :
|
||||
|
||||
```yml
|
||||
VITE_SOME_KEY=123
|
||||
DB_PASSWORD=foobar
|
||||
```
|
||||
|
||||
> 为了防止意外地将一些环境变量泄漏到客户端,只有以 `VITE_` 为前缀的变量才会暴露给经过 `vite` 处理的代码。
|
||||
|
||||
如上配置,只有 `VITE_SOME_KEY` 会被暴露为 `import.meta.env.VITE_SOME_KEY` 提供给客户端源码,而 `DB_PASSWORD` 则不会。
|
||||
|
||||
```js
|
||||
console.log(import.meta.env.VITE_SOME_KEY) // "123"
|
||||
console.log(import.meta.env.DB_PASSWORD) // undefined
|
||||
```
|
||||
|
||||
### mode 模式
|
||||
|
||||
Vite 允许你为不同的构建环境指定不同的模式。通常在 `npm scripts` 里面指定 `mode` 参数:
|
||||
|
||||
```sh
|
||||
"scripts": {
|
||||
"dev": "uni",
|
||||
"dev-dev": "uni --mode development",
|
||||
"dev-test": "uni --mode test",
|
||||
"dev-prod": "uni --mode production",
|
||||
}
|
||||
```
|
||||
|
||||
运行不同模式的脚本时,`Vite` 会自动加载对应的 `.env.[mode]` 文件,就能获取到不同的环境变量。
|
||||
|
||||
`Vite` 运行 `dev` 时默认会加载 `.env.development` 文件(若有)。
|
||||
|
||||
`Vite` 运行 `build` 时默认会加载 `.env.production` 文件(若有)。
|
||||
|
||||
故,如上配置 `pnpm dev` 与 `pnpm dev-dev` 是一个效果。
|
||||
|
||||
## `uni` 环境变量
|
||||
|
||||
`uni` 环境变量这里指运行 `uni` 的平台变量,通过 `vite` 的 `define` 配置可以暴露出来。
|
||||
|
||||
```
|
||||
define: {
|
||||
__UNI_PLATFORM__: JSON.stringify(UNI_PLATFORM),
|
||||
},
|
||||
```
|
||||
|
||||
代码里面使用:
|
||||
|
||||
```js
|
||||
export const platform = __UNI_PLATFORM__
|
||||
export const isH5 = __UNI_PLATFORM__ === 'h5'
|
||||
export const isApp = __UNI_PLATFORM__ === 'app'
|
||||
export const isMp = __UNI_PLATFORM__.startsWith('mp-')
|
||||
const PLATFORM = {
|
||||
platform,
|
||||
isH5,
|
||||
isApp,
|
||||
isMp,
|
||||
}
|
||||
export default PLATFORM
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
本文描写了 `vite` 环境变量和 `uni` 环境变量如何配置和使用。
|
||||
|
||||
全文完~
|
||||
67
docs/base/13-hbx.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# hbx 模板
|
||||
|
||||
为了方便使用 `HBuilderX` 的开发者,`unibest` 也提供 `hbx` 模板。
|
||||
|
||||
`hbx 模板` 适用于 `2 类用户`
|
||||
|
||||
- 使用 `uniCloud` 云开发的用户,必须使用 `hbx 版本`,因为 `uniCloud` 跟 `HBuilderX` 是绑定的。
|
||||
- 开发 `App` 的用户,可选使用 `hbx 版本`。
|
||||
|
||||
## 仓库地址
|
||||
|
||||
- gitee: [https://gitee.com/feige996/unibest-hbx.git](https://gitee.com/feige996/unibest-hbx.git)
|
||||
- github: [https://github.com/feige996/unibest-hbx.git](https://github.com/feige996/unibest-hbx.git)
|
||||
|
||||
没有梯子的用户优先推荐使用 `gitee` 仓库,速度更快。(两个仓库会实时同步,无差别。)
|
||||
|
||||
## 导入项目
|
||||
|
||||
有 2 种方式导入项目:
|
||||
|
||||
- 从 `Git` 导入...
|
||||
- 从本地目录导入...
|
||||
|
||||
## 运行项目
|
||||
|
||||
此时运行菜单会提示 `本项目类型无法运行`,如下图
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
需要执行如下 2 步:
|
||||
|
||||
- 项目下执行 `pnpm i`
|
||||
- 右键项目,选择 `重新识别项目类型`
|
||||
|
||||

|
||||
|
||||
## 运行效果
|
||||
|
||||
经过上面的操作后,就可以正常运行了。
|
||||
|
||||
- ios 模拟器运行效果如下:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
- 微信小程序运行效果如下:
|
||||
|
||||

|
||||
|
||||
> 目前微信小程序静态资源还有点问题,如下图 `logo 不见了`,后续会修复。
|
||||
|
||||

|
||||
|
||||
> 另外还发现 `UnoCSS Icon` 不生效,原因未知。
|
||||
|
||||
## 总结
|
||||
|
||||
本文描述了 `hbx` 模板的由来,使用方式。
|
||||
|
||||
有需要的可以试试,但是不太建议使用。另外精力有限,该模板不再维护。
|
||||
|
||||
全文完~
|
||||
116
docs/base/14-faq.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# 常见问题
|
||||
|
||||
本篇介绍一些常见的问题,会持续更新。
|
||||
|
||||
## 1. 如何设置/修改首页?
|
||||
|
||||
`vue` 文件的 `route-block` 块里面设置 `type="home"` 即可,请确保项目里面 `只有一个页面` 是这个配置。
|
||||
|
||||
> 注意:如果有多个,会按照字母顺序排列,第一个是首页。(可能不是您的想要的效果。)
|
||||
|
||||
## 2. 修改 `pages.json`、`manifest.json` 被覆盖问题
|
||||
|
||||
- `pages.json`
|
||||
|
||||
本项目引入了 `@uni-helper/vite-plugin-uni-pages`,`pages.json` 文件将会自动生成,手动修改 `pages.json` 将会被覆盖。
|
||||
|
||||
全局的东西请在 `pages.config.ts` 里面配置,页面的东西请在 `vue` 文件的 `route-block` 配置。
|
||||
|
||||
- `manifest.json`
|
||||
|
||||
与上面类似。本项目引入了 `@uni-helper/vite-plugin-uni-manifest`,`manifest.json` 文件将会自动生成,手动修改 `manifest.json` 将会被覆盖。
|
||||
|
||||
如需修改,请在 `manifest.config.ts` 里面修改。
|
||||
|
||||
## 3. 怎么分包?
|
||||
|
||||
`vite.config.ts` 里面有一个配置,如下:(其中 `subPackages` 就是用来分包的)
|
||||
|
||||
```ts [vite.config.ts]{3}
|
||||
UniPages({
|
||||
exclude: ['**/components/**/**.*'],
|
||||
subPackages: ['src/pages-sub'], // 是个数组,可以配置多个
|
||||
}),
|
||||
```
|
||||
|
||||
## 4. 首次运行 `pnpm:mp` 时报错。
|
||||
|
||||
首次运行 `pnpm:mp` 时报错,报错如下:
|
||||
|
||||
```text
|
||||
Error: ENOENT: no such file or directory, open '/Users/burtlai/unibest-projects/unibest/src/manifest.json'
|
||||
```
|
||||
|
||||
首次运行 `非h5端` 时都可能出现上面的问题,需要先执行一下 `pnpm i` 以生成 `src/manifest.json` 文件,后面就不会报错了。
|
||||
|
||||
## 5. `git commit` 报错。
|
||||
|
||||
请看 `commitlint.config.ts` 里面的配置,需要满足对应的设定。根据自己的需要,可以修改 `commitlint.config.ts` 里面的配置。
|
||||
|
||||
如果是一次的(比如引入了某个第三方库),可以通过 `--no-verify` 参数跳过校验:
|
||||
|
||||
```sh
|
||||
git commit -m "feat: xxx" --no-verify
|
||||
```
|
||||
|
||||
第三方库还有另外一种处理方式,放到特定的文件夹,然后在 `.eslintignore` 和 `.styleintignore` 里面加上该文件夹。
|
||||
|
||||
## 6. `uni-app` 无法使用 `process.env` 变量,怎么办?
|
||||
|
||||
使用 `import.meta.env` 替代!
|
||||
|
||||
## 7. 如何跟随 `uni-app` 官方升级?
|
||||
|
||||
项目下,执行 `npx @dcloudio/uvm@latest` 即可更新。
|
||||
|
||||

|
||||
|
||||
> 注意,上面的命令会自动安装 `vue-i18n`,可以手动删除(`pnpm un vue-i18n`),也可以不理它(没多大影响)。
|
||||
|
||||
## 8. 如何把已经加入 `git` 管理的文件移出 `git` 管理?
|
||||
|
||||
- 第一步,先把文件移出`git` 管理,操作如下:
|
||||
|
||||
```text
|
||||
# git rm -r --cached file1 file2 ## 针对某些文件
|
||||
# git rm -r --cached dir1 dir2 ## 针对某些文件夹
|
||||
# git rm -r --cached . ## 针对所有文件
|
||||
```
|
||||
|
||||
- 第二步,提交 `commit` 以正式删除的文件
|
||||
|
||||
> 总结:`git rm -r --cached .` + `git commit` 即可。
|
||||
|
||||
## 9. 支付宝小程序运行报错。
|
||||
|
||||
- 默认运行是会报错的,如下图
|
||||

|
||||
|
||||
- 只需要勾上 `本地开发跳过 ES5 转译` 即可正常运行,如下图
|
||||

|
||||
|
||||
> 总结:勾上 `本地开发跳过 ES5 转译` 即可。
|
||||
|
||||
## 10. 支持 `uni-app x` 吗?
|
||||
|
||||
不支持。但我们一直保持关注。[uni-app x 传送门](https://doc.dcloud.net.cn/uni-app-x/)
|
||||
|
||||
目前 `unibest` 已经有 `hbx` 模板,后续接入 `uni-app x` 会很容易,坐等官方发布。
|
||||
|
||||
## 11. 为啥 `vue` 已经 `3.4+` 了,还不支持 `defineModel` ?
|
||||
|
||||
`uni-app` 官方虽然已经把 `vue` 升级到 `3.4+` 了,但是目前只有 `H5端` 支持 `defineModel`,其他端目前运行报错,详情请看 `uni-app` 官网的发布日志:
|
||||
|
||||
[HBuilder X - Release Notes](https://3085868976.hiecheimaetu.com:22443/qn-GO8xCsKgpKDZWIBAkVCUkI1EnGmQUMT4.update.dcloud.net.cn/hbuilderx/changelog/4.14.2024043013.html)
|
||||
|
||||
关键截图如下:
|
||||
|
||||

|
||||
|
||||
真实运行报错截图如下:(分别是 `小程序` 和 `APP` )
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
全文完~
|
||||
267
docs/base/15-faq.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 常见问题 2
|
||||
|
||||
## 1. `wot-ui` 的 `toast` + `message-box` 不生效。
|
||||
|
||||
- 1. `layout` 引入 `wot-ui` 的 `toast` + `message-box`。
|
||||
|
||||
```vue [src/layouts/default.vue]
|
||||
<!-- src/layouts/default.vue -->
|
||||
<template>
|
||||
<view>
|
||||
<slot />
|
||||
<wd-toast />
|
||||
<wd-message-box />
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
> `unibest@2.1.0` 开始已经默认引入。
|
||||
|
||||
- 2.页面使用
|
||||
|
||||
```ts
|
||||
import { useMessage } from 'wot-design-uni'
|
||||
|
||||
const message = useMessage()
|
||||
const handleClick = () => {
|
||||
// 顺便测试 message 的使用
|
||||
message.show('显示隐藏切换')
|
||||
}
|
||||
```
|
||||
|
||||
## 2. `uni-app` 插件市场的插件如何使用?
|
||||
|
||||
`hbx` 模板可以直接引入,不在讨论范围内,下面描述的是 `普通模板`。
|
||||
|
||||
> 如果该插件支持 `npm` 安装,则直接安装即可,推荐统一使用 `pnpm` 安装。接着根据该插件的文档使用即可。
|
||||
|
||||
下面描写的是不支持 `npm` 安装的插件。
|
||||
|
||||
这里以 `sp-editor` 富文本插件为例,[插件地址](https://ext.dcloud.net.cn/plugin?id=14726)
|
||||
|
||||
- 1. 下载 `uni-app` 插件市场的代码。(居然要登录+看广告)
|
||||
|
||||

|
||||
|
||||
- 2. 解压并拷贝到 `unibest` 项目的 `uni_modules` 目录下。
|
||||
|
||||

|
||||
|
||||
- 3. 整理插件文件夹名称,把 `sp-editor_1.3.7` 改为 `sp-editor`。
|
||||
|
||||
> 不改会报错,因为内部代码都是用 `sp-editor` 不带版本号的。会导致查找文件失败。
|
||||
|
||||

|
||||
|
||||
- 4. 代码直接使用,无需引入组件。( `uni-app插件` 有一套规范,`uni-app` 会自动查找,跟 `easycom` 类似。)
|
||||
|
||||
```html
|
||||
<template>
|
||||
<view class="home">
|
||||
<view class="editor-box">
|
||||
<sp-editor
|
||||
:toolbar-config="{
|
||||
excludeKeys: ['direction', 'date', 'lineHeight', 'letterSpacing', 'listCheck'],
|
||||
iconSize: '18px',
|
||||
}"
|
||||
@init="initEditor"
|
||||
@input="inputOver"
|
||||
@upinImage="upinImage"
|
||||
@overMax="overMax"
|
||||
@addLink="addLink"
|
||||
@exportHtml="exportHtml"
|
||||
></sp-editor>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
完整版见下:
|
||||
:::details
|
||||
|
||||
```vue
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'demo',
|
||||
style: { navigationBarTitleText: '富文本' },
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="home">
|
||||
<view class="editor-box">
|
||||
<sp-editor
|
||||
:toolbar-config="{
|
||||
excludeKeys: ['direction', 'date', 'lineHeight', 'letterSpacing', 'listCheck'],
|
||||
iconSize: '18px',
|
||||
}"
|
||||
@init="initEditor"
|
||||
@input="inputOver"
|
||||
@upinImage="upinImage"
|
||||
@overMax="overMax"
|
||||
@addLink="addLink"
|
||||
@exportHtml="exportHtml"
|
||||
></sp-editor>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const editorIns = ref(null)
|
||||
|
||||
/**
|
||||
* 获取输入内容
|
||||
* @param {Object} e {html,text} 内容的html文本,和text文本
|
||||
*/
|
||||
function inputOver(e) {
|
||||
// 可以在此处获取到编辑器已编辑的内容
|
||||
console.log('==== inputOver :', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* 超出最大内容限制
|
||||
* @param {Object} e {html,text} 内容的html文本,和text文本
|
||||
*/
|
||||
function overMax(e) {
|
||||
// 若设置了最大字数限制,可在此处触发超出限制的回调
|
||||
console.log('==== overMax :', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑器就绪
|
||||
* @param {Object} editor 编辑器实例,你可以自定义调用editor实例的方法
|
||||
* @tutorial editor组件 https://uniapp.dcloud.net.cn/component/editor.html#editor-%E7%BB%84%E4%BB%B6
|
||||
* @tutorial 相关api https://uniapp.dcloud.net.cn/api/media/editor-context.html
|
||||
*/
|
||||
function initEditor(editor) {
|
||||
editorIns.value = editor // 保存编辑器实例
|
||||
// 保存编辑器实例后,可以在此处获取后端数据,并赋值给编辑器初始化内容
|
||||
preRender()
|
||||
}
|
||||
|
||||
function preRender() {
|
||||
setTimeout(() => {
|
||||
// 异步获取后端数据后,初始化编辑器内容
|
||||
editorIns.value.setContents({
|
||||
html: `<div> 猫猫<img src="https://img.yzcdn.cn/vant/cat.jpeg"/></div>`,
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接运行示例工程插入图片无法正常显示的看这里
|
||||
* 因为插件默认采用云端存储图片的方式
|
||||
* 以$emit('upinImage', tempFiles, this.editorCtx)的方式回调
|
||||
* @param {Object} tempFiles
|
||||
* @param {Object} editorCtx
|
||||
*/
|
||||
function upinImage(tempFiles, editorCtx) {
|
||||
/**
|
||||
* 本地临时插入图片预览
|
||||
* 注意:这里仅是示例本地图片预览,因为需要将图片先上传到云端,再将图片插入到编辑器中
|
||||
* 正式开发时,还请将此处注释,并解开下面 使用 uniCloud.uploadFile 上传图片的示例方法 的注释
|
||||
* @tutorial https://uniapp.dcloud.net.cn/api/media/editor-context.html#editorcontext-insertimage
|
||||
*/
|
||||
// #ifdef MP-WEIXIN
|
||||
// 注意微信小程序的图片路径是在tempFilePath字段中
|
||||
editorCtx.insertImage({
|
||||
src: tempFiles[0].tempFilePath,
|
||||
width: '80%', // 默认不建议铺满宽度100%,预留一点空隙以便用户编辑
|
||||
success: function () {},
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
editorCtx.insertImage({
|
||||
src: tempFiles[0].path,
|
||||
width: '80%', // 默认不建议铺满宽度100%,预留一点空隙以便用户编辑
|
||||
success: function () {},
|
||||
})
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 使用 uniCloud.uploadFile 上传图片的示例方法(可适用多选上传)
|
||||
* 正式开发环境中,请将上面 本地临时插入图片预览 注释后,模仿以下写法
|
||||
*/
|
||||
// tempFiles.forEach(async (item) => {
|
||||
// uni.showLoading({
|
||||
// title: '上传中请稍后',
|
||||
// mask: true
|
||||
// })
|
||||
// let upfile = await uniCloud.uploadFile({
|
||||
// filePath: item.path,
|
||||
// // 同名会导致报错 policy_does_not_allow_file_overwrite
|
||||
// // cloudPath可由 想要存储的文件夹/文件名 拼接,若不拼文件夹名则默认存储在cloudstorage文件夹中
|
||||
// cloudPath: `cloudstorage/${item.name}`,
|
||||
// cloudPathAsRealPath: true
|
||||
// })
|
||||
// editorCtx.insertImage({
|
||||
// src: upfile.fileID,
|
||||
// width: '80%', // 默认不建议铺满宽度100%,预留一点空隙以便用户编辑
|
||||
// success: function () {
|
||||
// uni.hideLoading()
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出 - toolbar需要开启export工具
|
||||
* @param {string} e 导出的html内容
|
||||
*/
|
||||
function exportHtml(e) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/out/out',
|
||||
success(res) {
|
||||
// 传至导出页面解析即可
|
||||
res.eventChannel.emit('e-transmit-html', {
|
||||
data: e,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加超链接
|
||||
* @param {Object} e { text: '链接描述', href: '链接地址' }
|
||||
*/
|
||||
function addLink(e) {
|
||||
console.log('==== addLink :', e)
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 3. Vue-Office 使用哪个版本?
|
||||
|
||||
使用 `1.8x`,而不是 `2.x`,否则出现下面这样的问题:
|
||||
|
||||

|
||||
|
||||
## 4. 为啥不用 `vant-ui`?
|
||||
|
||||
`vant-ui` 是 `WEB` 端 `UI 库`,不适用于 `uni-app`。
|
||||
|
||||
`uni-app` 没有 `window`, `document` 等 `WEB API`,所以凡是使用 `WEB API` 的 `框架`、`UI 库` 等都不适用于 `uni-app`。
|
||||
|
||||
## 4. 控制台报错 `[plugin:uni:mp-using-component] Unexpected token S in JSON at position 208`。
|
||||
|
||||
控制台报错如下:
|
||||

|
||||
|
||||
原因是 `uni-pages` 这个插件最新版本 `0.2.22` 有问题,需要回退到 `0.2.20`。
|
||||
|
||||

|
||||
|
||||
执行如下命令即可:
|
||||
|
||||
```
|
||||
pnpm add @uni-helper/vite-plugin-uni-pages@0.2.20
|
||||
```
|
||||
|
||||
> 因为 `unibest` 在 `2.3.0(含)` 之前没有把 `pnpm-lock.yaml` 加入到版本管理,导致小版还是有细微差别。
|
||||
>
|
||||
> 在 `2.4.0` 开始已经加入,不会再出现这个问题。
|
||||
119
docs/base/2-start.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 快速开始
|
||||
|
||||
- 前置依赖
|
||||
|
||||
- **Node.js** - `>=v18`
|
||||
- **pnpm** - `>=7.30`(推荐使用 `8.12+`)
|
||||
- **`VSCode`** - 可选 `WebStrom`
|
||||
- **`HBuilderX`** - `APP` 的运行和发布还是离不开它
|
||||
- **Vue-Office** - `1.8x`,别升到 `2.x` !
|
||||
|
||||
## 创建项目
|
||||
|
||||
通过下面的命令可以快速生成项目模板,`pnpm create unibest <项目名称>` ,如果不写 `<项目名称>` 会进入命令行交互模式。
|
||||
|
||||
```bash
|
||||
# 如果没有 pnpm,请先安装: npm i -g pnpm
|
||||
pnpm create unibest my-project
|
||||
```
|
||||
|
||||
npm 创建如下(不推荐)
|
||||
:::details
|
||||
如果使用 `npm`,可能有缓存,需要加上 `@latest` 标识,如果创建失败,请使用 `pnpm` 安装。
|
||||
|
||||
```bash
|
||||
npm create unibest my-project
|
||||
# 如果提示报错,或者生成的项目版本太旧,请使用下面的命令,增加 @latest 标识
|
||||
npm create unibest@latest my-project
|
||||
```
|
||||
|
||||
:::
|
||||
实际操作截图如下:
|
||||
|
||||

|
||||
|
||||
`create-unibest` 在 `v1.10.0` 开始会有版本号,如下:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
`create unibest` 支持 `-t` 参数选择模板,目前已有两大类 `8` 个模板
|
||||
|
||||
- `普通` 模板( `4个` ):分别是 `base`、`tabbar`、`i18n`、`demo`、~~`js`~~
|
||||
- `hbx` 模板(`2个` ):分别是 `hbx-base`、`hbx-demo`。
|
||||
|
||||
不带 `-t` 参数时会默认生成 `base` 模板。
|
||||
|
||||
`base` 模板是最基本的模板,更新最及时,推荐使用 `base` 模板创建新项目。其他几个模板也是基于 `base` 模板得到的。 `demo` 模板则作为参考用。
|
||||
|
||||
`js` 模板不推荐使用,可以使用 `base` 模板替代,里面已经做了兼容配置,可以直接编写 `js`,原本的 `ts` 文件还能提供部分类型,何乐而不为?
|
||||
|
||||
```sh
|
||||
# VS Code 模板
|
||||
pnpm create unibest my-project # 默认用 base 模板
|
||||
|
||||
pnpm create unibest my-project -t base # 基础模板
|
||||
pnpm create unibest my-project -t tabbar # 自定义 tabbar 模板
|
||||
pnpm create unibest my-project -t i18n # 多语言模板
|
||||
pnpm create unibest my-project -t demo # 所有demo的模板(包括i18n)
|
||||
# pnpm create unibest my-project -t js # js 模板
|
||||
|
||||
# HBuilderX 模板,方便使用 uniCloud 云开发 (未来可以对接 uni-app x)
|
||||
pnpm create unibest my-project -t hbx-base # hbx的base模板
|
||||
pnpm create unibest my-project -t hbx-demo # hbx的demo模板,包含所有的demo
|
||||
```
|
||||
|
||||
## 项目仓库地址
|
||||
|
||||
`github` 和 `gitee` 实时同步,代码一致。
|
||||
|
||||
### 普通模板:
|
||||
|
||||
- https://github.com/feige996/unibest
|
||||
- https://gitee.com/feige996/unibest
|
||||
|
||||
> `demo` 模板是在 `hello-unibest` 项目中,仓库地址如下:
|
||||
|
||||
- https://github.com/feige996/hello-unibest
|
||||
- https://gitee.com/feige996/hello-unibest
|
||||
|
||||
### hbx 模板
|
||||
|
||||
- https://github.com/feige996/unibest-hbx
|
||||
- https://gitee.com/feige996/unibest-hbx
|
||||
|
||||
> `hbx` 目前由 `青谷` 大佬维护,微信号:`qingguxixi`,[青谷 github 地址](https://github.com/Xiphin) 。
|
||||
|
||||
## 安装、运行
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm i
|
||||
pnpm dev
|
||||
# dev默认运行的是h5,其他平台执行dev:<uni-platform>,如:
|
||||
pnpm dev:mp-weixin
|
||||
```
|
||||
|
||||
`pnpm dev` 之后在浏览器打开 `http://localhost:9000/`。
|
||||
|
||||
> 其他平台构建和发布,查看 [运行发布篇](./11-build)。
|
||||
|
||||
## 第一次 `commit`
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: init project"
|
||||
```
|
||||
|
||||
## `v3` 代码块
|
||||
|
||||
在 `vue` 文件中,输入 `v3` 按 `tab` 即可快速生成页面模板,可以大大加快页面生成。
|
||||
|
||||
> 原理:基于 `VSCode` 代码块生成。
|
||||
|
||||

|
||||
|
||||
## 注意事项
|
||||
|
||||
- 若代码里面自动引入的 `API` 报错,只需要 `pnpm dev` 即可。
|
||||
- 若代码运行后,`H5端` 浏览器界面底部没有 `tabbar`, 刷新浏览器或者再次 `pnpm dev` 即可。
|
||||
25
docs/base/20-best.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 最佳实践
|
||||
|
||||
新项目使用 `base` 模板,可选 `tabbar` 模板。如果需要多语言,可以选 `i18n` 模板。
|
||||
|
||||
同时参考 `demo` 模板,可以直接 `clone` `demo` 项目,用来参考用。
|
||||
|
||||
> 推荐先全部体验一下 `demo` 的示例
|
||||
|
||||
```sh
|
||||
# 新项目创建
|
||||
pnpm create unibest my-project -b base
|
||||
# 参考项目
|
||||
git clone https://github.com/feige996/hello-unibest unibest-demo
|
||||
# 参考项目-gitee (与 github 同步,无梯子用户优先使用 gitee)
|
||||
git clone https://gitee.com/feige996/hello-unibest unibest-demo
|
||||
```
|
||||
|
||||
## 必看章节
|
||||
|
||||
- [介绍](/base/1-introduction)
|
||||
- [快速开始](/base/2-start)
|
||||
- [uni 插件](/base/3-plugin)
|
||||
- [常见问题](/base/14-faq)
|
||||
- [常见问题 2](/base/15-faq)
|
||||
- [运行发布](/base/11-build)
|
||||
158
docs/base/3-plugin.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# uni 插件
|
||||
|
||||
## 引言
|
||||
|
||||
有群友第一次看到 `unibest` 里面 `vue` 文件 `route-block` 这种写法,表示很奇怪,重来没见过!
|
||||
|
||||
```vue
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'demo',
|
||||
style: {
|
||||
navigationBarTitleText: '标题',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="text-green-500">菲鸽,你好,我喜欢你!</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
## uni 插件总览
|
||||
|
||||
哈哈,这个当然是 `uni插件` 的功劳了,具体点是 `@uni-helper/vite-plugin-uni-pages` 插件的功劳,该插件由 `uni-helper` 官方团队开发。
|
||||
|
||||
本文就来说说 `unibest` 都引入了哪些有用的 `uni插件`。下面这个表格描述了各个插件的主要作用。
|
||||
|
||||
| 插件名 | 作用 |
|
||||
| :----------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| @dcloudio/vite-plugin-uni | **最核心的 `uni 插件`**,没有它就不能在 vite 项目跑 uniapp,其他所有的 `uni插件` 都需要经通过它的手来编译,所以写法上,都是先写 `UniXXX`,再写 `Uni`,见下文 |
|
||||
| @uni-helper/vite-plugin-uni-pages | `uni 插件`,也是 `unibest 灵魂插件`,`route-block` 就是它的功劳,让你可以直接在本文件就能设置页面的路元信息,无需跑去 `pages.json` 配置,同时支持 `pages.config.ts` 编写 `pages.json` |
|
||||
| @uni-helper/vite-plugin-uni-layouts | `uni 插件`,支多种 `layouts` 布局,群友脑洞大开,充分利用这个特性实现平时不容实现的写法 |
|
||||
| @uni-helper/vite-plugin-uni-manifest | `uni 插件`,支持 `manifest.config.ts` 编写 `manifest.json` |
|
||||
|
||||
`UniXXX()` 插件都需要在 `uni()` 之前引入,因为最终都需要 `Uni` 来处理所有的代码。如下图:
|
||||

|
||||
|
||||
接下来介绍一下 `uni 插件`,其他 `通用插件` 大家都比较熟悉,不再赘述。
|
||||
|
||||
`unibest` 引入了 `uni-helper` 团队的几个重要插件,少了它们 `unibest` 就缺少了灵魂,感谢 `uni-helper` 团队的贡献。`Uni 插件` 列表如下:
|
||||
|
||||
- `vite-plugin-uni-pages`
|
||||
|
||||
- 介绍:为 `Vite` 下的 `uni-app` 提供基于文件系统的路由
|
||||
- 额外:使用 `TypeScript` 来编写 `uni-app` 的 `pages.json`
|
||||
- 访问地址:[@uni-helper/vite-plugin-uni-pages](https://github.com/uni-helper/vite-plugin-uni-pages)
|
||||
|
||||
- `vite-plugin-uni-layouts`
|
||||
|
||||
- 介绍:为 `Vite` 下的 `uni-app` 提供类 `nuxt` 的 `layouts` 系统
|
||||
- 访问地址:[@uni-helper/vite-plugin-uni-layouts](https://github.com/uni-helper/vite-plugin-uni-layouts)
|
||||
|
||||
- `vite-plugin-uni-manifest`
|
||||
|
||||
- 介绍:使用 `TypeScript` 来编写 `uni-app` 的 `manifest.json`
|
||||
- 访问地址:[@uni-helper/vite-plugin-uni-manifest](https://github.com/uni-helper/vite-plugin-uni-manifest)
|
||||
|
||||
## vite-plugin-uni-pages
|
||||
|
||||
得益于 [@uni-helper/vite-plugin-uni-pages](https://github.com/uni-helper/vite-plugin-uni-pages),约定式路由(文件路由)的实现轻而易举。
|
||||
|
||||
`src/pages` 目录下的每个文件都代表着一个路由。要创建新页面,只需要在这个目录里新增 `.vue` 文件,插件会自动生成对应的 `pages.json` 文件。
|
||||
|
||||
`route` 代码块则可以配置页面相关信息,这些信息会自动同步到 `page.json`,无需切换到 `page.json` 进行配置。
|
||||
|
||||
> `pages.json` 文件是自动生成的,请不要手动修改,全局的东西请在 `pages.config.ts` 里面配置,页面上的东西请在 `vue` 文件的 `route` 代码块配置,如下图。
|
||||
|
||||
```vue [src/pages/index.vue]
|
||||
<!-- 使用 type="home" 属性设置首页,其他页面不需要设置,默认为page -->
|
||||
<!-- 推荐使用json5,更强大,且允许注释 -->
|
||||
<route lang="json5" type="home">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '首页',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<div>
|
||||
<h1>欢迎使用 unibest</h1>
|
||||
<h4>unibest 是最好的 uniapp 开发模板</h4>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```vue [src/pages/about.vue]
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '关于',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view>
|
||||
<view>通过 `/pages/about` 来访问这个页面</view>
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 设置首页
|
||||
|
||||
通过在 `route-block` 里面配置 `type="home"` 即可,尽量保证一个项目 `只有一个` 这个配置,如果有多个,会按照字母顺序来排列,最终可能不是您想要的效果。
|
||||
|
||||
### 设置 pages 过滤和分包
|
||||
|
||||
- 过滤:默认 `src/pages` 里面的 `vue` 文件都会生成一个页面,如果不需要生成页面可以对 `vite.config.ts` 中的 `UniPages` 进行 `exclude` 配置。
|
||||
|
||||
- 分包:如果需要设置 `分包` 则可以通过 `subPackages` 进行配置,该配置项是个数组,可以配置多个 `分包`,注意分包的目录不能为 `src/pages` 里面的子目录。
|
||||
|
||||
```ts [vite.config.ts]
|
||||
UniPages({
|
||||
exclude: ['**/components/**/**.*'],
|
||||
subPackages: ['src/pages-sub'], // 是个数组,可以配置多个,但不能为 `src/pages` 里面的子目录
|
||||
})
|
||||
```
|
||||
|
||||
## vite-plugin-uni-layouts
|
||||
|
||||
得益于 [@uni-helper/vite-plugin-uni-layouts](https://github.com/uni-helper/vite-plugin-uni-layouts),你可以轻松地切换不同的布局。
|
||||
|
||||
`src/layouts` 文件夹下的 `vue` 文件都会自动生成一个布局,默认的布局文件名为 `default` ,路径 `src/layouts/default.vue` 。
|
||||
|
||||
如果需要修改使用的布局,可以通过 `vue` 文件内 `route` 代码块指定需要的布局,如下示例使用 `demo` 布局。
|
||||
|
||||
```vue [src/pages/demo.vue]{3}
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'demo',
|
||||
style: {
|
||||
navigationBarTitleText: '关于',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
```
|
||||
|
||||
```vue [src/layouts/demo.vue]
|
||||
<template>
|
||||
<view>
|
||||
<!-- 这里可以写通用的布局,比如导航栏,tabbar等 -->
|
||||
<!-- slot里面装的就是子页面的内容 -->
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
## vite-plugin-uni-manifest
|
||||
|
||||
得益于 [@uni-helper/vite-plugin-uni-manifest](https://github.com/uni-helper/vite-plugin-uni-manifest),你可以使用 `TypeScript` 来编写 `manifest.json`。
|
||||
|
||||
> `manifest.json` 文件是自动生成的,请不要手动修改,需要配置的内容请在 `manifest.config.ts` 里面配置。
|
||||
|
||||
## 总结
|
||||
|
||||
本文介绍了 `unibest` 引入的几个重要的 `uni插件`。
|
||||
|
||||
如果还想了解更多信息,可以去 `uni-helper` [github 仓库](https://github.com/uni-helper) 看看。
|
||||
220
docs/base/4-style.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# 样式篇
|
||||
|
||||
本篇主要介绍 `UnoCSS` 的使用,以及如何与 `设计稿尺寸` 对应。
|
||||
|
||||
## UnoCSS
|
||||
|
||||
[UnoCSS](https://unocss.dev/) 是按需使用的原子 CSS 引擎,提供了良好的样式支持。
|
||||
|
||||

|
||||
|
||||
在 VSCode 中还可以预览,
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
> 如果原子化 `UnoCSS` 没有预览效果,请安装 `VSCode` 插件 `antfu.unocss`。
|
||||
|
||||
如果不记得原子类,可以查 `UnoCSS 的原子类`,[UnoCSS Interactive](https://unocss.dev/interactive/),如下图
|
||||

|
||||
|
||||
也可以查看 `tailwindcss` 的原子类,更加清晰明了,[链接 - tailwindcss](https://tailwindcss.com/),如下图:
|
||||
|
||||

|
||||
|
||||
## 常用的原子类
|
||||
|
||||
- 宽高内外边距: `w-2`, `h-4`, `px-6`, `mt-8`等
|
||||
- 前景色背景色:`text-green-400`, `bg-green-500`
|
||||
- border: `border-2`, `border-solid`, `border-green-600`, `b-r-2` (注意 `border` = `border-1`,就是说边框 `1px` 时,一般简写为 `border` )
|
||||
- border-radius: `rounded-full`, `rounded-6`, `rounded-sm` (不是 `br-10`, 也不是 `b-r-10`)
|
||||
- line-height: `leading-10` (不是 `l-10`, 也不是 `lh-10`)
|
||||
- hover: `hover:text-green-200`, `hover:bg-green-300`, `hover:border-dashed`
|
||||
- flex: `flex`, `items-center`, `justify-center`, `flex-1`
|
||||
|
||||
## `UnoCSS` 配置
|
||||
|
||||
下面内容选读:
|
||||
|
||||
:::details
|
||||
`unocss.config.ts` 文件内容如下:
|
||||
|
||||
```ts
|
||||
// uno.config.ts
|
||||
import {
|
||||
type Preset,
|
||||
defineConfig,
|
||||
presetUno,
|
||||
presetAttributify,
|
||||
presetIcons,
|
||||
transformerDirectives,
|
||||
transformerVariantGroup,
|
||||
} from 'unocss'
|
||||
|
||||
import { presetApplet, presetRemRpx, transformerAttributify } from 'unocss-applet'
|
||||
|
||||
// @see https://unocss.dev/presets/legacy-compat
|
||||
import { presetLegacyCompat } from '@unocss/preset-legacy-compat'
|
||||
|
||||
const isMp = process.env?.UNI_PLATFORM?.startsWith('mp') ?? false
|
||||
|
||||
const presets: Preset[] = []
|
||||
if (isMp) {
|
||||
// 使用小程序预设
|
||||
presets.push(presetApplet(), presetRemRpx())
|
||||
} else {
|
||||
presets.push(
|
||||
// 非小程序用官方预设
|
||||
presetUno(),
|
||||
// 支持css class属性化
|
||||
presetAttributify(),
|
||||
)
|
||||
}
|
||||
export default defineConfig({
|
||||
presets: [
|
||||
...presets,
|
||||
// 支持图标,需要搭配图标库,eg: @iconify-json/carbon, 使用 `<button class="i-carbon-sun dark:i-carbon-moon" />`
|
||||
presetIcons({
|
||||
scale: 1.2,
|
||||
warn: true,
|
||||
extraProperties: {
|
||||
display: 'inline-block',
|
||||
'vertical-align': 'middle',
|
||||
},
|
||||
}),
|
||||
// 将颜色函数 (rgb()和hsl()) 从空格分隔转换为逗号分隔,更好的兼容性app端,example:
|
||||
// `rgb(255 0 0)` -> `rgb(255, 0, 0)`
|
||||
// `rgba(255 0 0 / 0.5)` -> `rgba(255, 0, 0, 0.5)`
|
||||
presetLegacyCompat({
|
||||
commaStyleColorFunction: true,
|
||||
}) as Preset,
|
||||
],
|
||||
/**
|
||||
* 自定义快捷语句
|
||||
* @see https://github.com/unocss/unocss#shortcuts
|
||||
*/
|
||||
shortcuts: [['center', 'flex justify-center items-center']],
|
||||
transformers: [
|
||||
// 启用 @apply 功能
|
||||
transformerDirectives(),
|
||||
// 启用 () 分组功能
|
||||
// 支持css class组合,eg: `<div class="hover:(bg-gray-400 font-medium) font-(light mono)">测试 unocss</div>`
|
||||
transformerVariantGroup(),
|
||||
// Don't change the following order
|
||||
transformerAttributify({
|
||||
// 解决与第三方框架样式冲突问题
|
||||
prefixedOnly: true,
|
||||
prefix: 'fg',
|
||||
}),
|
||||
],
|
||||
rules: [
|
||||
[
|
||||
'p-safe',
|
||||
{
|
||||
padding:
|
||||
'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
|
||||
},
|
||||
],
|
||||
['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
|
||||
['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
|
||||
],
|
||||
})
|
||||
|
||||
/**
|
||||
* 最终这一套组合下来会得到:
|
||||
* mp 里面:mt-4 => margin-top: 32rpx == 16px
|
||||
* h5 里面:mt-4 => margin-top: 1rem == 16px
|
||||
*
|
||||
* 另外,我们还可以推算出 UnoCSS 单位与设计稿差别4倍。
|
||||
* 375 * 4 = 1500,把设计稿设置为1500,那么设计稿里多少px,unocss就写多少述职。
|
||||
* 举个例子,设计稿显示某元素宽度100px,就写w-100即可。
|
||||
*
|
||||
* 如果是传统方式写样式,则推荐设计稿设置为 750,这样设计稿1px,代码写1rpx。
|
||||
* rpx是响应式的,可以让不同设备的屏幕显示效果保持一致。
|
||||
*/
|
||||
```
|
||||
|
||||
### UnoCSS presets
|
||||
|
||||
主要有 `4`个:
|
||||
|
||||
- `presetUno` —— `UnoCSS` 默认的预设,`H5端` 适用,`非H5端` 不支持,代码已经作区别处理。
|
||||
- `presetApplet` 小程序预设,因为默认 `Unocss 预设` 是针对 `WEB` 的,如果不加以处理,会报错,比如小程序不支持 `*`, 没有 `body` 等。该预设同样对 `APP` 生效。
|
||||
- `presetIcons`,专门使用 `UnoCSS Icons` 的,需要搭配图标库使用,eg: `@iconify-json/carbon`, 代码编写如 `<button class="i-carbon-sun dark:i-carbon-moon" />`
|
||||
- `presetLegacyCompat` 针对低端 `APP` 不认识新的函数颜色的兼容性预设,可以将颜色函数 `rgb()和hsl()` 里面空格分隔转换为逗号分隔,更好的兼容性`APP`端,example:
|
||||
> `rgb(255 0 0)` -> `rgb(255, 0, 0)`
|
||||
>
|
||||
> `rgba(255 0 0 / 0.5)` -> `rgba(255, 0, 0, 0.5)`
|
||||
|
||||
### UnoCSS shortcuts
|
||||
|
||||
```ts
|
||||
/**
|
||||
* 自定义快捷语句
|
||||
* @see https://github.com/unocss/unocss#shortcuts
|
||||
*/
|
||||
shortcuts: [['center', 'flex justify-center items-center']],
|
||||
```
|
||||
|
||||
可以编写一些常用的快捷类名,如上表示 `center` 就是 `flex justify-center items-center` 的组合,合理的添加快捷类名可以加快样式编写。
|
||||
|
||||
:::
|
||||
|
||||
## 设计稿尺寸
|
||||
|
||||
不同的编写方式,需要设置不同的设计稿尺寸,请看下文:
|
||||
|
||||
### 1. 传统编写方式
|
||||
|
||||
如果有设计稿,通常使用传统的编写 `CSS` 的方式,里面的对应尺寸规律如下。以蓝湖为例,假如设计稿宽度为 `750px`,则直接复制样式代码到 css 代码,同时把 `px` 批量替换为 `rpx` 即可。
|
||||
|
||||
如果设计稿不是 `750px` 可以调整蓝湖的设置,让设计稿宽度为 `750px`。
|
||||
|
||||
> 下面为一段辅助说明文案,从 `uniapp` 官网搬运而来。
|
||||
|
||||
`rpx` 是相对于基准宽度的单位,可以根据屏幕宽度进行自适应。`uni-app` 规定屏幕基准宽度 `750rpx`。
|
||||
|
||||
开发者可以通过设计稿基准宽度计算页面元素 `rpx` 值,设计稿 `1px` 与框架样式 `1rpx` 转换公式如下:
|
||||
|
||||
`设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx`
|
||||
|
||||
换言之,页面元素宽度在 `uni-app` 中的宽度计算公式:
|
||||
|
||||
`750 * 元素在设计稿中的宽度 / 设计稿基准宽度`
|
||||
|
||||
举例说明:
|
||||
|
||||
若设计稿宽度为 `750px`,元素 `A` 在设计稿上的宽度为 `100px`,那么元素 `A` 在 `uni-app` 里面的宽度应该设为:`750 * 100 / 750`,结果为:`100rpx`。
|
||||
|
||||
若设计稿宽度为 `640px`,元素 `A` 在设计稿上的宽度为 `100px`,那么元素 `A` 在 `uni-app` 里面的宽度应该设为:`750 * 100 / 640`,结果为:`117rpx`。
|
||||
|
||||
若设计稿宽度为 `375px`,元素 `B` 在设计稿上的宽度为 `200px`,那么元素 `B` 在 `uni-app` 里面的宽度应该设为:`750 * 200 / 375`,结果为:`400rpx`。
|
||||
|
||||
### 2. UnoCSS 编写方式
|
||||
|
||||
经过上一节的 `unocss.config.ts` 配置,可以得到下面的组合:
|
||||
|
||||
> mp 里面:mt-4 => margin-top: 32rpx == 16px
|
||||
>
|
||||
> h5 里面:mt-4 => margin-top: 1rem == 16px
|
||||
|
||||
我们还是把设计稿设置为 `750`,设计稿上多少 `px` 的元素,写成多少 `rpx` 即可。
|
||||
|
||||
元素 `A` 在设计稿上的宽度为 `100px`,则写 `w-100rpx` 即可。
|
||||
|
||||
就是把 `传统编写方式` 中写在 `css` 中的样式搬到了 `UnoCSS` 中。
|
||||
|
||||
如果要想用 `w-100` 这种方式,需要做额外的处理(待验证):
|
||||
|
||||
:::details
|
||||
太忙了,有空再写吧。
|
||||
:::
|
||||
|
||||
## 总结
|
||||
|
||||
本文主要介绍了 `UnoCSS` 的使用,以及 `unocss.config.ts` 中的一些配置项。
|
||||
|
||||
同时说明了设计稿在两种编写方式下的宽度的设置,分别为 `750` 和 `1500`.
|
||||
|
||||
最后说明一下,`原子化CSS` 和 `传统方式` 两者不是互斥的,他们是互补的,合适的地方使用合适的方式。
|
||||
189
docs/base/5-icons.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# 图标篇
|
||||
|
||||
本文主要介绍了 `图标` 的使用方式,通常有以下几种方式使用图标:
|
||||
|
||||
- `UI 库 Icons`
|
||||
- `UnoCSS Icons`
|
||||
- `iconfont`
|
||||
|
||||
下面笔者一一介绍
|
||||
|
||||
## UI 库 Icons
|
||||
|
||||
如果您已经引入了 `UI库`,并且正好该 `UI库` 已经有你想要的 `Icons`,那直接用最方便了,无需额外引入其他库,代码也是最少的。
|
||||
|
||||
这里介绍几个常用 `UI库` 的图标使用。
|
||||
|
||||
### `uni-ui Icons`
|
||||
|
||||
> 注意:`uni-ui Icons` 颜色只能通过 `color` 属性设置;使用 `UnoCSS` 设置无效。
|
||||
|
||||
```html
|
||||
<uni-icons type="contact" size="30"></uni-icons>
|
||||
<uni-icons type="contact" size="30" color="red"></uni-icons>
|
||||
<uni-icons type="contact" size="30" class="text-green"></uni-icons>
|
||||
<uni-icons type="contact" size="30" color="red" class="text-green"></uni-icons>
|
||||
```
|
||||
|
||||

|
||||
|
||||
### `wot-ui Icons`
|
||||
|
||||
> 注意:`wot-ui icons` 颜色可以通过 `color` 属性设置,也可以通过 `UnoCSS` 设置;同时设置时,`color` 属性优先级高。
|
||||
|
||||
```html
|
||||
<wd-icon name="add-circle"></wd-icon>
|
||||
<wd-icon name="add-circle" color="red"></wd-icon>
|
||||
<wd-icon name="add-circle" class="text-green"></wd-icon>
|
||||
<wd-icon name="add-circle" class="text-green" color="red"></wd-icon>
|
||||
```
|
||||
|
||||

|
||||
|
||||
### `uv-ui Icons`
|
||||
|
||||
> 注意:跟 `uni-ui Icons` 一样,`uv-ui Icons` 的颜色只能通过 `color` 属性设置;使用 `UnoCSS` 设置无效。
|
||||
|
||||
```html
|
||||
<uv-icon name="home"></uv-icon>
|
||||
<uv-icon name="home" color="red"></uv-icon>
|
||||
<uv-icon name="home" class="text-green"></uv-icon>
|
||||
<uv-icon name="home" color="red" class="text-green"></uv-icon>
|
||||
```
|
||||
|
||||

|
||||
|
||||
> 注意,经过检测这 `3个UI库Icons` 都不支持使用 `UnoCSS` 改变大小(优先级低被覆盖),必须使用 `size` 属性来设置大小才有效果(行内样式优先于 css 样式)。
|
||||
>
|
||||
> 另外,经过检测,都支持动态 `iconName`和动态 `color` ! 即下面这样的写法是生效的:
|
||||
|
||||
```ts
|
||||
const iconName = ref<string>('contact')
|
||||
const colorName = ref<string>('red')
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
iconName.value = 'chat'
|
||||
colorName.value = 'green'
|
||||
}, 1000)
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<uni-icons :type="iconName" :color="colorName" class="text-green w-8"></uni-icons>
|
||||
<!-- 其他2个UI库同样生效 -->
|
||||
```
|
||||
|
||||
## `UnoCSS Icons`
|
||||
|
||||
`UnoCSS Icons` 可以方便接入 `iconify` 图标库,后者拥有 `10万+` 的海量图标,总能找到你想要的。
|
||||
|
||||
### 1. 安装 iconify
|
||||
|
||||
在使用 `iconify` 之前需要安装对应的图标库,安装格式如下:
|
||||
|
||||
`pnpm i -D @iconify-json/[the-collection-you-want]`
|
||||
|
||||
以安装 `carbon` 为例,执行 `pnpm i -D @iconify-json/carbon` 即可。
|
||||
|
||||
> `unibest` 已经装好了 `carbon` 图标库,可以直接使用。
|
||||
|
||||
### 2. 找到 iconify 想要的图标名
|
||||
|
||||
打开网址:<https://icones.js.org/>
|
||||
|
||||
- 在里面找到某个库,如 `carbon`。
|
||||
|
||||

|
||||
|
||||
- 搜索想要的图表,如 `avatar`,出现的搜索结果,查看类名,也可以点击图标,会出现详情( `details` 里面)。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
- 如上图( `details` 里面),拿到 `carbon:user-avatar`。
|
||||
|
||||
### 3. 编写代码
|
||||
|
||||
- 代码里面 `class` 填写 `i-carbon-user-avatar`(所有的单词用中划线连接即可)并且支持改颜色。
|
||||
|
||||
```html
|
||||
<view class="i-carbon-user-avatar text-red" />
|
||||
```
|
||||
|
||||

|
||||
|
||||
> 如果图标没有预览效果,请安装 `VSCode` 插件 `antfu.iconify`。
|
||||
|
||||
预览效果:
|
||||
|
||||

|
||||
|
||||
### 4. 动态图标名
|
||||
|
||||
昨天有网友反馈,`UnoCSS Icons` 无法使用动态类名,我来试试:(我先说结论:是支持的!)
|
||||
|
||||
```ts
|
||||
const iconName = ref<string>('i-carbon-car')
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
iconName.value = 'i-carbon-user-avatar'
|
||||
}, 1000)
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<view :class="iconName" />
|
||||
```
|
||||
|
||||
一秒后会由 `i-carbon-car`(一辆车) 变成 `i-carbon-user-avatar`(一个头像),一切都是 OK 的。
|
||||
|
||||
> 但是注意,跨文件的话动态图标名不能生效。
|
||||
|
||||
## iconfont 图标库
|
||||
|
||||
`iconfont` 同样有海量免费的图标,同时支持上传自己的图标。公司项目通常会有自己的图标,由专业的 `UI设计师` 设计,这时通常会使用 `iconfont` 方式使用图标。
|
||||
|
||||
- 1. 打开`阿里巴巴矢量图标库 iconfont`,地址:[https://www.iconfont.cn/](https://www.iconfont.cn/),并登录。
|
||||
- 2. 寻找需要的图标,加入项目,也可以上传自己的图标。
|
||||
- 3. 图标方式选择 `Font class`,`项目设置` 勾选上 `base64`,否则`非H5端` 不支持,然后点击生成链接。
|
||||
|
||||

|
||||

|
||||
|
||||
- 4. 把上面的 `css` 链接里面的内容写入在 `style/iconfont.css`,并引入到 `style/index.scss`。
|
||||
- 5. 页面上直接写 `<i class="iconfont icon-package text-red"></i>` 即可!
|
||||
|
||||
```html
|
||||
<view class="m-4">
|
||||
<text mr-2>iconfont:</text>
|
||||
<i class="iconfont icon-package text-red"></i>
|
||||
<i class="iconfont icon-chat text-red"></i>
|
||||
<i class="iconfont icon-my text-red"></i>
|
||||
</view>
|
||||
```
|
||||
|
||||
预览如下:
|
||||
|
||||

|
||||
|
||||
> 上面的选择有疑问的可以看详细版 - [iconfont 详细版](/other/iconfont/iconfont)
|
||||
|
||||
## 其它图标库
|
||||
|
||||
其他优秀的可以免费商用的图标库:
|
||||
|
||||
- 字节跳动的 `IconPark`,链接 [https://iconpark.oceanengine.com](https://iconpark.oceanengine.com/)。
|
||||
- 不知道谁家的 `yesicon`,链接 [https://yesicon.app](https://yesicon.app/)。
|
||||
|
||||
## 总结
|
||||
|
||||
本文介绍了 `3` 种使用图标的方式,分别是 `UI 库 Icons`、`UnoCSS Icons`、`iconfont`。
|
||||
|
||||
- `UI 库 Icons` 颜色和大小属性都主要由 `UI 库` 本身控制,且都支持动态图标名和动态颜色。
|
||||
|
||||
- `UnoCSS Icons` 最省心,强烈推荐使用。
|
||||
|
||||
- `iconfont` 需要勾选 `Base64` 才能兼容多端。
|
||||
|
||||
全文完~
|
||||
181
docs/base/6-svg.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# SVG 篇
|
||||
|
||||
上一章《五、图标篇》主要介绍了 `线上图标` 的使用,今天带给大家本地 `SVG` 图标的使用。
|
||||
|
||||
本地 `SVG` 图标使用方式主要有:
|
||||
|
||||
- `image + src` 方式
|
||||
|
||||
- `static目录` 图标
|
||||
- `相对目录` 图标
|
||||
- `线上地址` 图标
|
||||
|
||||
> **`图片`** 也是使用上面几种方式。
|
||||
|
||||
## `image + src` 方式
|
||||
|
||||
根据图片地址不同,分为 2 种:`static目录`图标 , `相对目录`图标。
|
||||
|
||||
### 1. `static目录` 图标
|
||||
|
||||
这种方式直接编写代码即可,如下:
|
||||
|
||||
```html
|
||||
<image src="/static/svg/demo.svg" mode="scaleToFill" class="h-20 w-20" />
|
||||
```
|
||||
|
||||
### 2. `相对目录` 图标
|
||||
|
||||
这种方式需要先引入,再使用,代码编写如下:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<image :src="iconUrl" mode="scaleToFill" class="h-20 w-20" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import iconUrl from './demo.svg'
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3. `线上地址` 图标
|
||||
|
||||
这种方式直接使用,代码编写如下:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<image src="https://xxx.com/demo.svg" mode="scaleToFill" class="h-20 w-20" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## 其他
|
||||
|
||||
> `SvgComponent` 方式 和 `SvgIcon` 方式,仅 `H5端` 适用,感兴趣的可以阅读下
|
||||
|
||||
:::details
|
||||
|
||||
### `SvgComponent` 方式
|
||||
|
||||
从 `Web端` 过来的同学都知道 `SvgComponent` 这种方式,只需要引入 `vite-svg-loader` 插件即可,支持 `3种` 方式引入 `svg`: `url`, `raw`, `component`。
|
||||
|
||||
- URL
|
||||
|
||||
SVGs can be imported as URLs using the `?url` suffix:
|
||||
|
||||
```js
|
||||
import iconUrl from './my-icon.svg?url'
|
||||
// 'data:image/svg+xml...'
|
||||
```
|
||||
|
||||
Used in template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<image :src="iconUrl" mode="scaleToFill" class="h-20 w-20" />
|
||||
</template>
|
||||
```
|
||||
|
||||
- Raw
|
||||
|
||||
SVGs can be imported as strings using the `?raw` suffix:
|
||||
|
||||
```js
|
||||
import iconRaw from './my-icon.svg?raw'
|
||||
// '<?xml version="1.0"?>...'
|
||||
```
|
||||
|
||||
Used in template:
|
||||
|
||||
```html
|
||||
<template>{{ iconRaw }}</template>
|
||||
```
|
||||
|
||||
- Component
|
||||
|
||||
SVGs can be explicitly imported as Vue components using the `?component` suffix:
|
||||
|
||||
```js
|
||||
import IconComponent from './my-icon.svg?component'
|
||||
// <IconComponent />
|
||||
```
|
||||
|
||||
Used in template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<IconComponent />
|
||||
</template>
|
||||
```
|
||||
|
||||
但是目前经过测试,只有 `url` 的方式所有端可以使用,与上面的 `image + src - 相对目录 图标` 是一个效果。至于 `component` 只有 `H5端生效`,其他端不行。
|
||||
|
||||
### `SvgIcon` 方式
|
||||
|
||||
从 `Web端` 过来的同学都知道 `SvgIcon` 这种方式,只需要引入 `vite-plugin-svg-icons` 插件 + `vite 配置`,再编写一个通用的 `SvgIcon` 即可,但是同样只有 `H5端生效`,其他端不行。
|
||||
|
||||
`vite` 配置如下:
|
||||
|
||||
```
|
||||
createSvgIconsPlugin({
|
||||
// 指定要缓存的文件夹
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets')],
|
||||
// 指定symbolId格式
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
}),
|
||||
```
|
||||
|
||||
如上,只需要把 `svg` 放到 `src/assets` 目录即可。
|
||||
|
||||
`SvgIcon` 代码如下:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<svg aria-hidden="true">
|
||||
<use :href="symbolId" :fill="color" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="SvgIcon">
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
prefix?: string
|
||||
name: string
|
||||
color?: string
|
||||
}>(),
|
||||
{
|
||||
prefix: 'icon',
|
||||
name: '',
|
||||
color: '#333',
|
||||
},
|
||||
)
|
||||
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
|
||||
</script>
|
||||
```
|
||||
|
||||
使用方式如下:
|
||||
|
||||
```html
|
||||
<!-- src/assets/demo.svg -->
|
||||
<SvgIcon name="demo" class="h-20 w-20"></SvgIcon>
|
||||
|
||||
<!-- src/assets/dir/demo.svg -->
|
||||
<SvgIcon name="dir-demo" class="h-20 w-20"></SvgIcon>
|
||||
```
|
||||
|
||||
> `SvgComponent` 依赖 `vite-svg-loader` 插件
|
||||
>
|
||||
> `SvgIcon` 依赖 `vite-plugin-svg-icons` 插件
|
||||
|
||||
:::
|
||||
|
||||
## 总结
|
||||
|
||||
本地 `svg` 的使用方式,如果要全端适配,那就只能使用 `image + src` 的方式。
|
||||
|
||||
> `SvgComponent` 依赖 `vite-svg-loader` 插件
|
||||
>
|
||||
> `SvgIcon` 依赖 `vite-plugin-svg-icons` 插件
|
||||
|
||||
其他 2 种方式 —— `SvgComponent` + `SvgIcon` 仅 `h5` 端生效,其他端都不能用,既然不能使用,那就删了,对应的 2 个插件也一起删了,目前 `base` 分支已经删了。
|
||||
|
||||
全文完~
|
||||
120
docs/base/7-ui.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# UI 库替换篇
|
||||
|
||||
## 默认 UI 库
|
||||
|
||||
`unibest` 经过几次更迭,先后使用 `uni-ui`、`uv-ui`作为默认 UI 库,目前使用 `wot-ui` 为默认 UI 库。
|
||||
|
||||
`wot-ui` 是 `vue3+ts` 编写的全端支持的 UI 库,编码体验比 `uv-ui` 更好;而官方维护的 `uni-ui` 则样式略丑,组件较少,故弃之。
|
||||
|
||||
> `wot-ui` 全称 `wot-design-uni`,是 `wot-design` 的 `uniapp` 版本,文档地址:[https://wot-design-uni.netlify.app/](https://wot-design-uni.netlify.app/).
|
||||
|
||||
---
|
||||
|
||||
很多群友反馈有其他 `UI` 库的需求,那么更换 `UI 库` 需要哪些步骤呢?
|
||||
|
||||
- 先卸载原有的 `wot-ui` 库
|
||||
- 再安装其他 `UI 库`
|
||||
|
||||
下面我们简单描述一下更换 2 个主流 `UI库` —— `uni-ui` + `uv-ui` 的过程。
|
||||
|
||||
> 当然也支持同时存在多个 `UI 库`,有 ES 摇树特性,不必担心打包后的体积。
|
||||
|
||||
## 卸载 wot-ui 库
|
||||
|
||||
卸载 `wot-ui` 过程如下:
|
||||
|
||||
- 1. 删除 `wot-ui` 库:
|
||||
|
||||
```sh
|
||||
pnpm un wot-design-uni
|
||||
```
|
||||
|
||||
- 2. `pages.config.ts` 文件 `easycom.custom` 删除相关配置:
|
||||
|
||||
```diff
|
||||
easycom: {
|
||||
autoscan: true,
|
||||
custom: {
|
||||
- '^wd-(.*)': 'wot-design-uni/components/wd-$1/wd-$1.vue',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
- 3. ` tsconfig.json` 文件 `compilerOptions.types` 删除相关配置:
|
||||
|
||||
```diff
|
||||
"types": [
|
||||
"@dcloudio/types",
|
||||
"@types/wechat-miniprogram",
|
||||
- "wot-design-uni/global.d.ts",
|
||||
"./components.d.ts",
|
||||
"./global.d.ts"
|
||||
]
|
||||
```
|
||||
|
||||
## 安装 `uni-ui` 库
|
||||
|
||||
- 1. 安装 `uni-ui` 库:
|
||||
|
||||
```sh
|
||||
pnpm add @dcloudio/uni-ui
|
||||
```
|
||||
|
||||
- 2. `pages.config.ts` 文件 `easycom.custom` 添加相关配置:
|
||||
|
||||
```diff
|
||||
easycom: {
|
||||
autoscan: true,
|
||||
custom: {
|
||||
+ '^uni-(.*)': '@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
- 3. ` tsconfig.json` 文件 `compilerOptions.types` 添加相关配置:
|
||||
|
||||
```diff
|
||||
"types": [
|
||||
"@dcloudio/types",
|
||||
"@types/wechat-miniprogram",
|
||||
+ "@uni-helper/uni-ui-types",
|
||||
"./components.d.ts",
|
||||
"./global.d.ts"
|
||||
]
|
||||
```
|
||||
|
||||
## 安装 `uv-ui` 库
|
||||
|
||||
- 1. 安装 `uv-ui` 库:
|
||||
|
||||
```sh
|
||||
pnpm add @climblee/uv-ui
|
||||
```
|
||||
|
||||
- 2. `pages.config.ts` 文件 `easycom.custom` 添加相关配置:
|
||||
|
||||
```diff
|
||||
easycom: {
|
||||
autoscan: true,
|
||||
custom: {
|
||||
+ '^uv-(.*)': '@climblee/uv-ui/components/uv-$1/uv-$1.vue',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
- 3. ` tsconfig.json` 文件 `compilerOptions.types` 添加相关配置:
|
||||
|
||||
```diff
|
||||
"types": [
|
||||
"@dcloudio/types",
|
||||
"@types/wechat-miniprogram",
|
||||
+ "@ttou/uv-typings/shim",
|
||||
+ "@ttou/uv-typings/v2",
|
||||
"./components.d.ts",
|
||||
"./global.d.ts"
|
||||
]
|
||||
```
|
||||
|
||||
> 其他 UI 库的安装类似,不再赘述。
|
||||
|
||||
全文完~
|
||||
163
docs/base/8-request.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 请求篇
|
||||
|
||||
本篇分为三块内容:
|
||||
|
||||
- 普通请求
|
||||
- 图片上传
|
||||
- 多后台地址
|
||||
|
||||
## 普通请求
|
||||
|
||||
普通请求分 2 种处理,一种是只在页面请求一次的一次性请求,这种请求占大多数;一种是项目多处用到的请求,这种请求占小部分,需要单独编写一个请求函数放到 `api文件夹` or `service文件夹`。
|
||||
|
||||
> `unibest` 里面是使用 `service文件夹` 后面不再说明。
|
||||
|
||||
下面来分别演示:
|
||||
|
||||
### 一次性请求
|
||||
|
||||
`template` 部分编码如下:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<button @click="run">请求</button>
|
||||
<view v-if="loading" class="text-blue h-10">请求中...</view>
|
||||
<view v-if="error" class="text-red h-10">请求错误</view>
|
||||
<view v-else class="text-green h-10">{{ JSON.stringify(data) }}</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
`script` 部分使用 `菲鸽` 封装好的 `useRequest` 即可实现请求状态一体化,如下:
|
||||
|
||||
```ts
|
||||
<script setup>
|
||||
type IFooItem = { name: string }
|
||||
const { loading, error, data, run } = useRequest<IFooItem>(() => httpGet('/foo', { name: '菲鸽' }))
|
||||
</script>
|
||||
```
|
||||
|
||||
看吧,使用非常简单。
|
||||
|
||||
### 重复性请求
|
||||
|
||||
`重复性请求` 与 `一次性请求` 的 `html部分` 是一样的,唯一的区别是 `请求函数` 放到了 `service文件夹`,如下所示:
|
||||
|
||||
```ts
|
||||
<script setup>
|
||||
import { getFooAPI, IFooItem } from '@/service/index/foo' // 看这里
|
||||
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'))
|
||||
</script>
|
||||
```
|
||||
|
||||
对应的 `src/service/index/foo.ts` 文件如下:
|
||||
|
||||
```ts
|
||||
import { http, httpGet } from '@/utils/http'
|
||||
export interface IFooItem {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
/** GET 请求 */
|
||||
export const getFooAPI = (name: string) => {
|
||||
return http<IFooItem>({
|
||||
url: `/foo`,
|
||||
method: 'GET',
|
||||
query: { name },
|
||||
})
|
||||
}
|
||||
|
||||
/** GET 请求 - 再次简化,看大家是否喜欢这种简化 */
|
||||
export const getFooAPI2 = (name: string) => {
|
||||
return httpGet<IFooItem>('/foo', { name })
|
||||
}
|
||||
```
|
||||
|
||||
依然非常简洁,深受妹子喜爱。
|
||||
|
||||
## 图片上传
|
||||
|
||||
`template` 部分编码如下:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<view class="p-4 text-center">
|
||||
<wd-button @click="run">选择图片并上传</wd-button>
|
||||
<view v-if="loading" class="text-blue h-10">上传...</view>
|
||||
<template v-else>
|
||||
<view class="m-2">上传后返回的图片地址:</view>
|
||||
<view class="m-2">{{ data }}</view>
|
||||
<view class="h-80 w-full">
|
||||
<image v-if="data" :src="data" mode="scaleToFill" />
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
`script` 部分使用 `菲鸽` 封装好的 `useUpload` 即可实现请求状态一体化,如下:
|
||||
|
||||
```ts
|
||||
<script lang="ts" setup>
|
||||
const { loading, data, run } = useUpload<string>({ user: '菲鸽' })
|
||||
</script>
|
||||
```
|
||||
|
||||
使用非常简单,深受汉子和妹子的喜爱。
|
||||
|
||||
## 多后台地址
|
||||
|
||||
上面的 `普通请求` 默认是只有一个请求地址的,在 `.env` 里面配置 `VITE_SERVER_BASEURL`,如下:
|
||||
|
||||
```text
|
||||
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
```
|
||||
|
||||
并且在 `src/interceptors/request.ts` 里面有设置:
|
||||
|
||||
- 如果是 `http` 开头的请求路径,则直接请求
|
||||
- 如果不是,则拼接上 `VITE_SERVER_BASEURL`
|
||||
|
||||

|
||||
|
||||
但在多后台地址时就不能这么玩了,需要处理如下:(关注上图的箭头部分)
|
||||
|
||||
```ts
|
||||
// 可以写一个映射对象,如:
|
||||
const proxyMap = {
|
||||
cms:'http://localhost:8080/cms',
|
||||
ums:'http://localhost:8080/ums',
|
||||
}
|
||||
|
||||
// 拦截器部分(上图箭头部分)修改如下
|
||||
Object.keys(proxyMap).forEach(key=>{
|
||||
if(options.url.startsWith(`/${key}`)){
|
||||
options.url = proxyMap[key] + options.url
|
||||
}
|
||||
}
|
||||
|
||||
// 接口调用的地方使用如下格式:
|
||||
export const getFooAPI = (name: string) => {
|
||||
return http<IFooItem>({
|
||||
url: `/cms/foo`, // 看这里,前缀不用!!!
|
||||
method: 'GET',
|
||||
query: { name },
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
- `普通请求` 需要在 `.env` 里面配置 `VITE_SERVER_BASEURL`,用在 `src/interceptors/request.ts` 文件拼接请求地址;而 `多后台地址` 时则用不上,可以删除。
|
||||
|
||||
```text
|
||||
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
```
|
||||
|
||||
- `图片上传` 需要在 `.env` 里面配置 `VITE_UPLOAD_BASEURL`:
|
||||
|
||||
```text
|
||||
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload'
|
||||
```
|
||||
|
||||
全文完~
|
||||
165
docs/base/9-state.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# 状态篇
|
||||
|
||||
本文主要介绍了全局状态管理 `pinia` 和 简单状态 `ref` + `reactive`。
|
||||
|
||||
## pinia
|
||||
|
||||
`unibest` 已经内置了 `Pinia` + `pinia-plugin-persistedstate`(数据持久化插件),并提供了开箱即用的示例。
|
||||
|
||||
### 兼容性处理
|
||||
|
||||
本身 `pinia-plugin-persistedstate` 是不支持 `uniapp` 的,但是 `pinia-plugin-persistedstate` 提供了修改 `storage` 存储 API 的方式(默认是 `localStorage`,是一个 `WEB API`,`非H5端` 不支持),目前 `unibest` 已经处理好了。关键代码如下:
|
||||
|
||||
```ts
|
||||
import { createPinia } from 'pinia'
|
||||
import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化
|
||||
|
||||
const store = createPinia()
|
||||
store.use(
|
||||
createPersistedState({
|
||||
storage: {
|
||||
getItem: uni.getStorageSync, // 看这里
|
||||
setItem: uni.setStorageSync, // 看这里
|
||||
},
|
||||
}),
|
||||
)
|
||||
```
|
||||
|
||||
### 定义 `pinia` 全局状态
|
||||
|
||||
`src/store/xxx.ts` 里面编写代码,如下是 `src/store/count.ts` 文件。
|
||||
|
||||
注意 `defineStore` 第三个参数可以设置是否需要持久化,默认不需要。
|
||||
|
||||
```ts [src/store/count.ts]{26}
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useCountStore = defineStore(
|
||||
'count',
|
||||
() => {
|
||||
const count = ref(0)
|
||||
const increment = () => {
|
||||
count.value++
|
||||
}
|
||||
const decrement = () => {
|
||||
count.value--
|
||||
}
|
||||
const reset = () => {
|
||||
count.value = 0
|
||||
}
|
||||
return {
|
||||
count,
|
||||
decrement,
|
||||
increment,
|
||||
reset,
|
||||
}
|
||||
},
|
||||
{
|
||||
// 如果需要持久化就写 true, 不需要持久化就写 false(或者去掉这个配置项)
|
||||
persist: true,
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
> 请不要随意把数据丢到 `pinia`,能不用就不用。简单状态尽量使用 `ref` 或者 `reactive`。
|
||||
|
||||
### 使用 `pinia` 全局状态
|
||||
|
||||
在 `vue` 文件中就可以使用了,如下是 `src/pages/demo.vue` 文件:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="flex justify-center items-center text-blue-500 mt-4 mb-4">
|
||||
<view class="w-20">Count: {{ countStore.count }}</view>
|
||||
<button class="ml-2 mr-2" @click="countStore.decrement">-1</button>
|
||||
<button class="ml-2 mr-2" @click="countStore.increment">+1</button>
|
||||
<button class="ml-2 mr-2" @click="countStore.reset">重置</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useCountStore } from '@/store'
|
||||
|
||||
const countStore = useCountStore()
|
||||
</script>
|
||||
```
|
||||
|
||||
## 简单状态
|
||||
|
||||
你可以直接使用 `Vue` 提供的 `ref` 或 `reactive` 方法来做简单状态管理。
|
||||
|
||||
### ref
|
||||
|
||||
如下是 `src/pages/demo/useCount.ts` 文件,定义简单状态。
|
||||
|
||||
```ts [src/pages/demo/useCount.ts]
|
||||
// 全局状态
|
||||
const globalCount = ref(1)
|
||||
export function useCount() {
|
||||
// 本地状态
|
||||
const localCount = ref(1)
|
||||
function increment() {
|
||||
globalCount.value++
|
||||
localCount.value++
|
||||
}
|
||||
return {
|
||||
globalCount,
|
||||
localCount,
|
||||
increment,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如下是 `src/pages/demo/index.vue`,与 `ref` 简单状态文件放到同一个目录下,方便管理。
|
||||
|
||||
```vue [src/pages/demo/index.vue]
|
||||
<script setup lang="ts">
|
||||
import useCount from './useCount.ts'
|
||||
const { globalCount, localCount, increment } = useCount()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="increment()">
|
||||
{{ globalCount }}
|
||||
{{ localCount }}
|
||||
</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
## reactive
|
||||
|
||||
`reactive` 与 `ref` 类似。
|
||||
|
||||
如下是 `src/pages/demo/count.ts` 文件,定义状态。
|
||||
|
||||
```ts [src/pages/demo/count.ts]
|
||||
export const countStore = reactive({
|
||||
count: 0,
|
||||
increment() {
|
||||
this.count++
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
如下是 `src/pages/demo/index.vue`,与 `reactive` 简单状态文件放到同一个目录下,方便管理。
|
||||
|
||||
```vue [src/pages/demo/index.vue]
|
||||
<script setup lang="ts">
|
||||
import { countStore } from './count.ts'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="countStore.increment()">
|
||||
{{ countStore.count }}
|
||||
</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
本文介绍了 `unibest` 里面状态管理的 `2` 种方式:`pinia` 全局状态 和 `ref\reactive` 简单状态,分别演示了如何定义状态和使用状态。
|
||||
|
||||
注意需要灵活使用 `pinia` 和 `简单状态`,局部的状态尽量使用 `简单状态` 的方式来处理,减少 `pinia` 里面全局变量的数量。
|
||||
|
||||
全文完~
|
||||
BIN
docs/base/assets/1-1.png
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
docs/base/assets/10-1.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
docs/base/assets/10-2.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
docs/base/assets/10-3.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/base/assets/10-android.mp4
Normal file
BIN
docs/base/assets/10-ios.mp4
Normal file
BIN
docs/base/assets/11-1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/base/assets/11-10.png
Normal file
|
After Width: | Height: | Size: 485 KiB |
BIN
docs/base/assets/11-100.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/base/assets/11-11.png
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
docs/base/assets/11-12.png
Normal file
|
After Width: | Height: | Size: 484 KiB |
BIN
docs/base/assets/11-13.png
Normal file
|
After Width: | Height: | Size: 245 KiB |
BIN
docs/base/assets/11-2.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/base/assets/11-3.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
docs/base/assets/11-4.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
docs/base/assets/11-5.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/base/assets/11-6.png
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
docs/base/assets/11-7.png
Normal file
|
After Width: | Height: | Size: 642 KiB |
BIN
docs/base/assets/11-8.png
Normal file
|
After Width: | Height: | Size: 888 KiB |
BIN
docs/base/assets/11-9.png
Normal file
|
After Width: | Height: | Size: 705 KiB |
BIN
docs/base/assets/13-1.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/base/assets/13-2.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/base/assets/13-3.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/base/assets/13-4.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/base/assets/13-5.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
docs/base/assets/13-6.png
Normal file
|
After Width: | Height: | Size: 220 KiB |
BIN
docs/base/assets/13-7.png
Normal file
|
After Width: | Height: | Size: 211 KiB |
BIN
docs/base/assets/13-8.png
Normal file
|
After Width: | Height: | Size: 286 KiB |
BIN
docs/base/assets/14-1.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/base/assets/14-2.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
docs/base/assets/14-3.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/base/assets/14-4.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
docs/base/assets/14-5.png
Normal file
|
After Width: | Height: | Size: 513 KiB |
BIN
docs/base/assets/14-6.png
Normal file
|
After Width: | Height: | Size: 549 KiB |
BIN
docs/base/assets/15-1.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/base/assets/15-2.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
docs/base/assets/15-3.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/base/assets/15-4.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
docs/base/assets/15-5.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
docs/base/assets/15-6.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
docs/base/assets/2-1.png
Normal file
|
After Width: | Height: | Size: 246 KiB |
BIN
docs/base/assets/2-2.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/base/assets/2-3.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
docs/base/assets/2-4.gif
Normal file
|
After Width: | Height: | Size: 648 KiB |
BIN
docs/base/assets/3-1.png
Normal file
|
After Width: | Height: | Size: 536 KiB |
BIN
docs/base/assets/4-1.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
docs/base/assets/4-2.png
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
docs/base/assets/4-3.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
docs/base/assets/4-4.png
Normal file
|
After Width: | Height: | Size: 317 KiB |
BIN
docs/base/assets/4-5.png
Normal file
|
After Width: | Height: | Size: 542 KiB |
BIN
docs/base/assets/5-1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/base/assets/5-10.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/base/assets/5-100.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/base/assets/5-11.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
docs/base/assets/5-2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/base/assets/5-3.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
docs/base/assets/5-4.png
Normal file
|
After Width: | Height: | Size: 418 KiB |
BIN
docs/base/assets/5-5.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
docs/base/assets/5-6.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
docs/base/assets/5-7.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
docs/base/assets/5-8.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/base/assets/5-9.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/base/assets/8-1.png
Normal file
|
After Width: | Height: | Size: 534 KiB |
BIN
docs/base/image.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
docs/base/ui/image-1.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
docs/base/ui/image-2.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
docs/base/ui/image.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
125
docs/base/ui/ui.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# UI 库选型篇
|
||||
|
||||
## 背景
|
||||
|
||||
`unibest` 作为最好的 `uniapp` 开发模板,那 `UI 框架` 的选择也是要仔细斟酌的。
|
||||
|
||||
`unibest` 作为 `vue3` 项目,`vue2` 时代的 `uview` 就不考虑在内了。但是在 `uview` 的基础上衍生出来的支持 `vue3` 的 `uview 系` 的 `ui框架` 还有不少,而且热度很高。
|
||||
|
||||
官方维护的 `uni-ui`,支持全端,而且有类型提示,但样式略丑,且其他优秀的 `UI 库` 已经包含了 `uni-ui` 的组件,所以直接用第三方 `UI 库` 就好了。
|
||||
|
||||
> tip1: `uni-ui` 本身是 `js` 开发的,但是官方提供了完备的类型提示( by `@uni-helper/uni-ui-types`)所以看起来就像是 `ts` 开发的一样,开发体验很好。所有的组件都有提示,很方便,很贴心。
|
||||
|
||||
> tip2: 再次重申一下 `uview` 不支持 `Vue3`,不然又有人问我为啥不用 `uview`。(臣妾做不到啊~)
|
||||
|
||||
## UI 库总览
|
||||
|
||||
经过搜寻了一番,目前参加对比的 UI 框架有:
|
||||
|
||||
- uv-ui (uveiw 系) - [文档地址](https://www.uvui.cn/)
|
||||
- uview-plus (uveiw 系) - [文档地址](https://uiadmin.net/uview-plus/)
|
||||
- Wot Design Uni (wot 系) - [文档地址](https://wot-design-uni.netlify.app/)
|
||||
- TuniaoUI (图鸟系) - [文档地址](https://vue3.tuniaokj.com/zh-CN/)
|
||||
|
||||
还有 2 个 UI 框架也很优秀,但是只有部分组件开源免费,大半组件收费,咱暂不考虑。
|
||||
|
||||
- FirstUI [文档链接](https://doc.firstui.cn/)
|
||||
- ThorUI [文档链接](https://thorui.cn/doc/)
|
||||
|
||||
> 温馨提示:收费没有对错,只要做得好,提供优质的组件,别人愿意付费,也是极好的。
|
||||
|
||||
---
|
||||
|
||||
下面通过几个方面对 `UI 库` 进行对比
|
||||
|
||||
## 开源热度
|
||||
|
||||
截止到 `2024-05-30` 发表文章时的数据:
|
||||
|
||||
| UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
|
||||
| ------------ | :---: | :--------: | :----: | :------: |
|
||||
| github stars | 568 | 362 | 492 | 192 |
|
||||
| gitee stars | 555 | 126 | 35 | - |
|
||||
| github forks | 1.1k | 158 | 188 | 20 |
|
||||
| gitee forks | 75 | 4 | 30 | - |
|
||||
|
||||
其实到这里就一决高下了,`github star 数`: `uv-ui(568)` > `wot-ui(492)` > `uview-plus(362)` > `TuniaoUI(192)`,其中 `uv-ui` 和 `wot-ui` 拔得头筹。
|
||||
|
||||
[](https://star-history.com/#Moonofweisheng/wot-design-uni&climblee/uv-ui&ijry/uview-plus&tuniaoTech/tuniaoui-rc-vue3-uniapp&Date)
|
||||
|
||||
源码仓库地址展示如下,_纯粹为了方便大家查阅_ (虽然大概率你们也不会去访问,/手动狗头)
|
||||
|
||||
| UI 框架 | 文档地址 | github | gitee |
|
||||
| ---------- | ------------------------------------- | ------------------------------------------------------- | ------------------------------------------------- |
|
||||
| uv-ui | <https://www.uvui.cn/> | <https://github.com/climblee/uv-ui> | <https://gitee.com/climblee/uv-ui> |
|
||||
| uview-plus | <https://uiadmin.net/uview-plus/> | <https://github.com/ijry/uview-plus> | <https://gitee.com/uiadmin/uview-plus> |
|
||||
| wot-ui | <https://wot-design-uni.netlify.app/> | <https://github.com/Moonofweisheng/wot-design-uni> | <https://gitee.com/wot-design-uni/wot-design-uni> |
|
||||
| TuniaoUI | <https://vue3.tuniaokj.com/zh-CN/> | <https://github.com/tuniaoTech/tuniaoui-rc-vue3-uniapp> | - |
|
||||
|
||||
> 接着奏乐接着舞,我们继续正文 ^\_^
|
||||
|
||||
## 多端支持情况
|
||||
|
||||
| UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
|
||||
| ------------ | ----- | ---------- | ------ | -------- |
|
||||
| h5 | ✅ | ✅ | ✅ | ✅ |
|
||||
| app(ios) | ✅ | ✅ | ✅ | ✅ |
|
||||
| app(android) | ✅ | ✅ | ✅ | ✅ |
|
||||
| 微信小程序 | ✅ | ✅ | ✅ | ✅ |
|
||||
| 支付宝小程序 | ✅ | ✅ | ✅ | ✅ |
|
||||
| QQ 小程序 | ✅ | ✅ | ❌ | ❌ |
|
||||
| 百度小程序 | ✅ | ✅ | ❌ | ❌ |
|
||||
| 头条小程序 | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
## 组件数量
|
||||
|
||||
| UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
|
||||
| -------- | :---: | :--------: | :----: | :------: |
|
||||
| 总数 | 67 | 67 | 71 | 55 |
|
||||
| 基础组件 | 8 | 11 | 8 | 5 |
|
||||
| 表单组件 | 16 | 17 | 20 | 14 |
|
||||
| 数据组件 | 13 | 4 | 18 | 4 |
|
||||
| 反馈组件 | 8 | 10 | 16 | 8 |
|
||||
| 布局组件 | 7 | 9 | - | 8 |
|
||||
| 导航组件 | 8 | 8 | 9 | 5 |
|
||||
| 其他组件 | 7 | 8 | - | 5 |
|
||||
| 内容组件 | - | - | - | 6 |
|
||||
|
||||
组件数:`wot(71)` > `uv-ui(67)` = `uview-plus(67)` > `TuniaoUI(55)`
|
||||
|
||||
## `ts` 支持情况
|
||||
|
||||
查看 4 个组件库的源码,可以了解到:
|
||||
|
||||
- `uv-ui` 和 `uView-plus` 都是 `js` 写的,并非 `ts`,可以通过 `ttou/uv-typings` 提供类型支持。
|
||||
- `wot` 和 `TuniaoUI` 都是 `ts` 写的,编码体验会好很多。
|
||||
|
||||
> 小知识:代码里如何辨别一个库是否有 ts 支持,写代码的时候按 `ctrl + i` (Mac 里 `cmd + i`),如果有提示就是有,啥都没有就是没有。
|
||||
>
|
||||
> 举个例子,编写 `<xx-button type="" ...`,在 `type=""` 双引号里面按 `ctrl + i`,看提示就知道了。
|
||||
|
||||
- `wot` 有提示
|
||||
|
||||

|
||||
|
||||
- ~~`uv-ui` 无提示~~
|
||||
|
||||

|
||||
|
||||
把 `tsconfig.json` 文件里面 `types` 里面的 `@ttou/uv-typings/v3` 改为 `@ttou/uv-typings/v2` 就正常了(也是群友发现的),如下。
|
||||
|
||||

|
||||
|
||||
## `wot-ui` 和 `uv-ui` 皇城 `PK`
|
||||
|
||||
`wot-ui` 和 `uv-ui` 皇城 `PK`
|
||||
|
||||
[](https://star-history.com/#Moonofweisheng/wot-design-uni&climblee/uv-ui&Date)
|
||||
|
||||
目前 `wot-ui` 还是比不过 `uv-ui` 的,但是我 `wot-ui` 有反超的势头。主要是看了源码后,还是选定了 `vue3+ts` 编写的 `wot-ui`。
|
||||
|
||||
> 别说我偏心,两位 `ui` 框架的作者都是我的好友,我是 `uv-ui` 群的管理员,`wot-ui` 作者在我的大群里面。选择 `wot-ui` 确实因为它很优秀。
|
||||
|
||||
## 总结
|
||||
|
||||
很高兴我们已经为宇宙最强 `uniapp` 开发模板 `unibest` 选好了 `UI 组件库`,`wot-ui` 是最终的幸运儿。为此我特意去 `wot-ui` 官网里面捐赠了一杯咖啡钱给作者,开源不易,要支持一下。
|
||||