目录
一. 创建 uni-app 项目
二. 编译和运行 uni-app 项目
三. TS 类型校验
四. JSON 注释问题
五. 安装uview-plus
六. 配置pinia持久化
七. 封装http请求
搭建项目的准备工作:
通过vue-cli脚手架
创建 uni-app
项目,便于更好的兼容TS写法
node版本:v18.16.0
pnpm版本:8.3.0
vscode安装uni-app 开发插件:
一. 创建
uni-app
项目
主要是通过vue-cli脚手架
创建 uni-app
项目,便于更好的兼容TS写法,使用Vue3/Vite版:
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
注意:
^14.18.0 || >=16.0.0
更多的注意安装流程和注意事项可以参考官网:uni-app官网
二. 编译和运行 uni-app 项目
1. 安装依赖 pnpm install
2. 运行项目 pnpm dev:mp-weixin
在运行项目时,可以打开package.json文件,在scripts配置中可以查看到运行项目的命令,如果是运行微信小程序,则通过pnpm dev:mp-weixin,打包则是pnpm build:mp-weixin,当然也可以自行配置快捷启动命名哦,如"serve": "pnpm dev:mp-weixin";
运行完项目后,目录会生成dist文件夹,里面的dev中mp-weixin文件则是用于运行编译的文件;
3. 导入微信开发者工具
在运行项目完成后,按照提示运行方式:打开微信开发者工具, 导入 dist\dev\mp-weixin 运行,此时就可以在微信开发者工具成功运行并编译该项目;
三. TS 类型校验
打开项目结构,会发现tsconfig.json有报错提示:
Option 'importsNotUsedAsValues' is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption '"ignoreDeprecations": "5.0"' to silence this error.
Use 'verbatimModuleSyntax' instead.ts
描述:警告消息与 TypeScript 编译器选项的弃用有关importsNotUsedAsValues,并建议改用该verbatimModuleSyntax选项。要在 TypeScript 5.5 之前使错误消息静音,您可以添加ignoreDeprecations": "5.0"到编译器选项;
解决:可以在tsconfig.json文件中"compilerOptions"配置项内添加"ignoreDeprecations": "5.0"
"compilerOptions": {
"ignoreDeprecations": "5.0"
},
° 此时我们打开vue文件中,任意写一些组件,如:
在image内置组件的mode属性中很显然是没有“xxx”的属性值,但是代码中并没有错误提示,所以为了符合Ts校验,我们需要额外配置Ts类型校验:
1. 安装类型声明文件:
pnpm i -D @types/wechat-miniprogram @uni-helper/uni-app-types
2. 配置tsconfig.json:
// tsconfig.json
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": {
"ignoreDeprecations": "5.0",
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"lib": ["esnext","dom"],
"types": [
"@dcloudio/types", // uni-app API 类型
"miniprogram-api-typings", // 原生微信小程序类型
"@uni-helper/uni-app-types" // uni-app 组件类型
]
},
// vue 编译器类型,校验标签类型
"vueCompilerOptions": {
"nativeTags": ["block","component","template","slot"],
},
"include": ["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]
}
在配置完成后,刚才的vue组件就会提示报错信息,并且在image组件下方会有红色波浪线显示;
四. JSON 注释问题
在manifest.json和pages.json文件中,往往我们会添加一些注释信息,但是JSON规范不支持在文件中添加注释,会被视为无效的标记,并且会导致解析错误。
此时我们可以vscode工作区中进行配置:
在vscode面板中,点击右小角设置按钮→点击设置→在搜索设置中搜索“文件关联”→找到Files: Associations的配置项→点击添加项→把 manifest.json
和 pages.json
设置为 jsonc即可;
五. 安装uview-plus
我们使用的UI框架是uview-plus, uview-plus是基于uView2.0初步修改,支持vue3写法,组件也是很丰富的,这里会简单介绍一下安装以及配置的步骤,具体的详细步骤流程可以参考官网:uview-plus 3.0 - 全面兼容nvue的uni-app生态框架 - uni-app UI框架
1. 安装
pnpm add uview-plus
pnpm add dayjs
pnpm add clipboard
注意: 此安装方式必须要按照npm方式安装的配置中的说明配置了才可用,且项目名称不能有中文字符。
因为uview-plus依赖SCSS,所以必须要安装此插件,否则无法正常运行。
// 安装sass
pnpm add sass -D
// 安装sass-loader,注意需要版本10,否则可能会导致vue与sass的兼容问题而报错
pnpm add sass-loader@10 -D
2. 配置步骤
引入uview-plus主JS库:在项目src
目录中的main.js
中,引入并使用uview-plus的JS库,注意这两行要放在const app = createSSRApp(App)
之后。
// main.js
import uviewPlus from 'uview-plus'
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
app.use(uviewPlus)
return {
app
}
}
// #endif
引入uview-plus的全局SCSS主题文件: 在项目根目录的uni.scss
中引入此文件。
/* uni.scss */
@import 'uview-plus/theme.scss';
引入uview-plus基础样式: 在App.vue
中首行的位置引入,注意给style标签加入lang="scss"属性。
// App.vue
配置easycom组件模式:需要在项目src
目录的pages.json
中进行。
// pages.json
{
"easycom": {
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
"custom": {
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
}
},
// 此为本身已有的内容
"pages": [
// ......
]
}
注意:
在配置完后,可以发现在mian.ts中引入uview-plus时会提示ts报错:无法找到模块“uview-plus”的声明文件。
可以在src文件中创建一个types文件夹专门用来存放ts类型声明文件,在文件中新建uview.d.ts文件写入下方声明代码即可:
declare module "uview-plus"
3. 使用
下载和配置完成之后,在某个页面可以直接使用组件,无需通过import
引入组件
六. 配置pinia持久化
在vue3+vite中使用的状态管理库是pinia,官网:Pinia 中文文档
1. 安装pinia:使用 HBuilder X 不需要手动安装,直接使用即可。使用 CLI 需要手动安装:
pnpm add [email protected]
2. 用法:
//main.js
import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';
export function createApp() {
const app = createSSRApp(App);
app.use(Pinia.createPinia());
return {
app,
Pinia, // 此处必须将 Pinia 返回
};
}
创建创建一个 Store文件夹counter.ts
// stores/counter.js
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 };
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++;
},
},
});
在组件中使用它:
Current Count: {{ counter.count }}
注意:pinia和vuex同样有个缺点刷新页面后数据是会丢失的,所以一般登录的token等信息既会保存到store中也会保存到本地存储等,从而实现持久化存储。
这里我们实现持久化存储用到了插件 快速开始 | pinia-plugin-persistedstate
1. 安装插件
pnpm i pinia-plugin-persistedstate
2. 将插件添加到 pinia 实例上
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
3. 用法
创建 Store 时,将 persist
选项设置为 true
。
import { defineStore } from 'pinia'
export const useStore = defineStore(
'main',
() => {
const someState = ref('你好 pinia')
return { someState }
},
{
persist: true,
},
)
4. 多端兼容
export const useMemberStore = defineStore(
'main',
() => {
//…省略
},
{
// 配置持久化
persist: {
// 调整为兼容多端的API
storage: {
setItem(key, value) {
uni.setStorageSync(key, value)
},
getItem(key) {
return uni.getStorageSync(key)
},
},
},
},
)
七. 封装http请求
为了更方便的进行axios数据请求,可以将小程序的数据请求封装为Promise请求函数
1. 请求和上传文件拦截器
uniapp 拦截器: uni.addInterceptor
// src/utils/http.ts
// 请求基地址
const baseURL = 'xxxx'
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: UniApp.RequestOptions) {
// 1. 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时
options.timeout = 10000
// 3. 添加小程序端请求头标识
options.header = {
'source-client': 'miniapp',
...options.header,
}
// 4. 添加 token 请求头标识
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
},
}
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
2. 封装 Promise 请求函数
需求:返回 Promise 对象,用于处理返回值类型,成功通过resolve提取数据与添加泛型,失败通过reject捕捉错误。
/**
* 请求函数
* @param UniApp.RequestOptions
* @returns Promise
* 1. 返回 Promise 对象,用于处理返回值类型
* 2. 获取数据成功
* 2.1 提取核心数据 res.data
* 2.2 添加类型,支持泛型
* 3. 获取数据失败
* 3.1 401错误 -> 清理用户信息,跳转到登录页
* 3.2 其他错误 -> 根据后端错误信息轻提示
* 3.3 网络错误 -> 提示用户换网络
*/
type Data = {
code: string
msg: string
result: T
}
// 2.2 添加类型,支持泛型
export const http = (options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
// 状态码 2xx,参考 axios 的设计
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
resolve(res.data as Data)
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}
在项目配置过程中可以参考哔哩哔哩网站:Day1-01-uni-app小兔鲜儿导学视频_哔哩哔哩_bilibili
欢迎各位大佬讨论、提供建议补充...