uniapp的内容和vue网页开发会有很多区别,但是都是基于vue开发的,大多数业务还是在vue打交道,但是这些uniapp的特殊的知识点也是要掌握好的。
基本配置
创建uniapp项目
npx degit dcloudio/uni-preset-vue#vite-ts 项目名 :用于创建一个uniapp项目
npm run dev:mp-weixin :用于给项目打包成微信小程序的打包格式,接着直接将dist中相应的包导入到相应的微信开发者工具里面即可。
加上ts类型校验:npm i -D @types/wechat-miniprogram @uni-helper/uni-app-types
ts类型校验
接着在tsconfig.json配置文件中配置好这个类型校验:
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": {
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types",
"@types/wechat-miniprogram",//加上
"@uni-helper/uni-app-types"]//加上
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
uni-ui的支持
安装uni-helper/uni-ui-types:
npm i -D @uni-helper/ui-types
再把@uni-helper/uni-ui-types加上以上的type配置项中去。
"types": [
"@dcloudio/types",
"@types/wechat-miniprogram",//加上
"@uni-helper/uni-app-types",
"@uni-helper/uni-ui-types"]//加上
},
pinia配置
持久化配置:要先下载pinia持久化插件:
npm i pinia-plugin-persistedstate
插件默认使用 localStorage
实现持久化,小程序端不兼容,需要替换持久化 API。
store下的index.ts:
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)
// 默认导出,给 main.ts 使用
export default pinia
// 模块统一导出
export * from './modules/member'
main.ts:
import { createSSRApp } from "vue";
import App from "./App.vue";
import pinia from './stores'
export function createApp() {
const app = createSSRApp(App);
app.use(pinia)
return {
app,
};
}
要多端配置持久化,要在相应的store的ts文件中,配置持久化规则:
小程序端配置持久化persist,要专门配置下getItem和setItem:(在defineStore中配置此参数)
// TODO: 持久化
persist: {
storage:{
getItem(key){
return uni.getStorageSync(key)
},
setItem(key,value){
uni.setStorageSync(key,value)
}
}
}
封装promise请求函数和请求过滤器
import { useMemberStore } from "@/stores/modules/member"
import { BaseRequestUrl } from "./properties"
const baseURL = BaseRequestUrl
//添加拦截器
const httpInterceptor = {
invoke(option:UniApp.RequestOptions){
//非http开头的请求需要拼接地址
if(!option.url.startsWith('http')){
option.url = baseURL + option.url
}
//请求超时,默认是六十秒
option.timeout = 30000
console.log(option)
//添加小程序请求头标识
option.header = {
...option.header, //如果有原来的请求头,保留原来的请求头后再加上小程序请求头
'source-client':'miniapp'
}
//添加token请求头标识
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if(token){
option.header.Authorization = token
}
}
}
uni.addInterceptor('request',httpInterceptor)
uni.addInterceptor('uploadFile',httpInterceptor)
interface Data<T>{
code:string,
message:string,
data:T
}
export const sendRequest = <T>(option:UniApp.RequestOptions) => { //指定泛型,该泛型是有效数据的类型
return new Promise<Data<T>>((resolve,reject) => {
uni.request({
...option,
success(res){
if(res.statusCode >= 200 && res.statusCode < 300){ //如果是2xx,说明是
resolve(res.data as Data<T>) //后端响应过来的有效数据
}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<T>).message || '请求错误'
})
}
},fail(err){ //响应失败,一般是网络问题
uni.showToast({
icon:'none',
title:'网络错误'
})
reject(err)
}
})
})
}
其实就是小程序端使用uni.request来发送请求,自定义了一个promise,内部使用了uni.request函数,用于发送请求。uni.request返回的数据中,是属于后端返回的数据的是res中的data,所以要返回的就是res.data。Data接口是后端返回的数据类型的格式。token的信息也封装在其中,登录后获取token之后,token信息会储存在pinia中,每次发送请求的时候,token会自动被读取到请求头中。
baseUrl是服务器的url地址或者微服务网关的url地址。
关于pages.json
在uniapp中,每个页面都是要注册在pages.json文件中。
在pages.json中,配置页面的路由地址及窗口表现、默认窗口表现、tarbar
代码案例:
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",//可以在此处修改一些小程序的页面信息
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path" : "pages/my/my",
"style" :
{
"navigationBarTitleText" : "我的"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#2ff8d0",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"selectedColor": "#2ff8d0",//tarbar选中的时候的文字的颜色指定
"list": [
{
"pagePath": "pages/index/index",//tabar的路由
"text": "首页",//tabar下方的文字
"iconPath": "static/tabs/home_default.png",//tabar的图标
"selectedIconPath": "static/tabs/home_selected.png"//tabar被选中的时图标
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/tabs/user_default.png",
"selectedIconPath": "static/tabs/user_selected.png"
}
]
},
}
pages参数
pages参数是一个数组,数组中的元素就是一个一个的页面的信息,数组中的第一个元素代表的页面就是应用首页。
path就是页面的路由地址,之后关于路由跳转页面的时候,都是使用这个配置的路由地址。
style是页面的一些窗口表现配置。style用于设置每个页面的状态栏、导航条、标题、窗口背景色等。在pages参数外还有一个参数叫globalStyle,用于配置全局窗口表现,每个页面的实际的窗口表现会先找style,如果没有的话再找globalStyle。
常见的样式如下:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #F8F8F8 | 导航栏背景颜色(同状态栏背景色) |
navigationBarTextStyle | String | black | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white |
navigationBarTitleText | String | 导航栏标题文字内容 | |
navigationStyle | String | default | 导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
至于具体的样式,见
pages.json 页面路由 | uni-app官网
tarbar
tarbar是用于配置一级导航栏,即底部的那个导航栏。
常用配置属性:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
color | HexColor | 是 | tab 上的文字默认颜色 | |
selectedColor | HexColor | 是 | tab 上的文字选中时的颜色 | |
backgroundColor | HexColor | 是 | tab 的背景色 | |
list | Array | 是 | tab 的列表,详见 list 属性说明,最少2个、最多5个 tab | |
position | String | 否 | bottom | 可选值 bottom、top,用于控制一级导航栏是显示在底部还是顶部 |
tarbar参数中的list数组,是一级导航栏里面的tab导航的信息的数组,tar导航的顺序和数组中的一致,tarbar最多配置五个tab,最少配置两个tab。
tab的配置属性:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
pagePath | String | 是 | 页面路径,必须在 pages 中先定义 |
text | String | 是 | tab 上按钮文字,在 App 和 H5 平台为非必填。例如中间可放一个没有文字的+号图标 |
iconPath | String | 否 | 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 position 为 top 时,此参数无效,不支持网络图片,不支持字体图标 |
selectedIconPath | String | 否 | 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 position 为 top 时,此参数无效 |
visible | Boolean | 否 | 该项是否显示,默认显示 |
iconfont | Object | 否 | 字体图标,优先级高于 iconPath |
具体参数信息见官网文档:pages.json 页面路由 | uni-app官网
分包
pages.json中还可以进行分包配置,分包可以让一些页面和主要的页面分开下载,即进入程序的时候,会默认下载主包中的页面信息,而分包中的信息,在进入指定页面的时候,此分包才会开始下载页面信息,如此可以大大优化小程序的下载和启动速度。
分包中的页面不要放在src下的pages目录中,要自定义一个和pages目录同级的新目录,代表一个分包,将分包页面放在此分包的目录中。
例:若有个分包叫pagesMember,此分包下有两个页面:settings.vue,profile.vue
{
//组件自动导入的规则
"easycom": {
//是否开启自动扫描
"autoscan": true,
//以正则的方式自定义组件匹配规则
"custom": {
// uni-ui 规则如下配置
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom", //隐藏默认导航栏
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/my/my",
"style": {
"navigationStyle": "custom",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "我的"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
// 设置 TabBar
"tabBar": {
"color": "#333",
"selectedColor": "#27ba9b",
"backgroundColor": "#fff",
"borderStyle": "white",
"list": [
{
"text": "首页",
"pagePath": "pages/index/index",
"iconPath": "static/tabs/home_default.png",
"selectedIconPath": "static/tabs/home_selected.png"
}
{
"text": "我的",
"pagePath": "pages/my/my",
"iconPath": "static/tabs/user_default.png",
"selectedIconPath": "static/tabs/user_selected.png"
}
]
},
//分包信息配置
"subPackages": [
{
"root": "pagesMember",
"pages": [
{
"path": "settings/settings",
"style": {
"navigationBarTitleText": "设置"
}
},
{
"path": "profile/profile",
"style": {
"navigationStyle": "custom",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "个人信息详情页面"
}
}
]
}
],
//分包预下载规则
"preloadRule": {
"pages/my/my": {
"network": "all",
"packages": [
"pagesMember"
]
}
}
}
subPackages中,root是此分包中页面的的根目录,也就是以上自定义的那个pagesMember目录。
preloadRule就是指定,进入了哪个页面的时候,会下载哪个分包。参数名就是触发下载的页面的路径,参数值中的network是代表在什么网络环境下下载分包,packages是指定要加载哪些分包。
具体使用见:pages.json 页面路由 | uni-app官网
常用api
api比较多,我列举几个我觉得看了有用的api。例如上传文件、选择媒体资源上传到服务器、页面路由跳转、弹出窗口提示等。
uni.uploadFile()
此方法用于将文件数据上传到服务器中,请求方式是post,其中 content-type
为 multipart/form-data
。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
url | String | 是 | 开发者服务器 url |
fileType | String | 见平台差异说明 | 文件类型,image/video/audio |
file | File | 否 | 要上传的文件对象。 |
filePath | String | 是(files和filePath选其一) | 要上传文件资源的路径。 |
name | String | 是 | 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容 |
header | Object | 否 | HTTP 请求 Header, header 中不能设置 Referer。 |
timeout | Number | 否 | 超时时间,单位 ms |
formData | Object | 否 | HTTP 请求中其他额外的 form data |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'userInfo': userinfo.value
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
其中一定要注意的是,formData参数的参数值会变成一个json字符串请求给后端,后端可以在controller的方法的参数列表上,添加一个String的参数,在其前面的@RequestParam注解中,加上指定在formData中设置的key的名称,这个参数上就会接受到指定的formData中的相应的参数信息。
@PostMapping(value="/upload")
public ResultData<RoleContentPo> voiceMsgSend(@RequestParam("userInfo") String str, @RequestParam("file") MultipartFile file){
UserInfo userInfo = JSONObject.parseObject(str,UserInfo.class);
//其他操作
}
关于下载文件,没什么要特殊说明的,见文档:uni.uploadFile(OBJECT) | uni-app官网
uni.chooseMedia()
用于用户从自己的相册中选择图片或者启动拍照功能获取图片。
参数名 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
count | Number | 9(注意:ios不可大于9) | 否 | 最多可以选择的文件个数 |
mediaType | Array.<string> | ['image', 'video'] | 否 | 文件类型 |
sourceType | Array.<string> | ['album', 'camera'] | 否 | 图片和视频选择的来源 |
maxDuration | Number | 10 | 否 | 拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间 |
sizeType | Array.<string> | ['original', 'compressed'] | 否 | 仅对 mediaType 为 image 时有效,是否压缩所选文件 |
camera | String | 'back' | 否 | 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
代码案例:
uni.chooseMedia({
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
console.log(res.tempFiles)
}
})
res.tempFiles是选择的图片/视频的临时文件的路径的数组,其中的元素就是一个个临时文件的路径。
路由跳转
uni.navigateTo()
保留原有页面,跳转到指定的页面。要跳转到原来的页面,使用uni.navigateBack()即可跳回原来的页面。
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2',path为下一个页面的路径,下一个页面的onLoad函数可得到传递的参数 |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
uni.navigateTo({
url: '/pages/login/login?id=1&name=uniapp'
});
路由路径后面带的参数可以被下个页面的onLoad函数的参数中获取,当然也会作为query参数传递。
uni.redirectTo()
和uni.navigate使用方法一致,区别是,uni.redirectTo()是关闭当前页面,跳转到指定页面,类似一个替换的效果。
uni.reLaunch()
使用也是和以上两个一致,区别是,它使用后,会关闭此前的所有的页面,跳转到指定页面。
uni.switchTab()
以上的四个api都是只能用于打开非tab页面,要想打开tab页面,要使用uni.switchTab,使用方法和以上四个是一致的。只是页面路径要是tab页面。并且使用了该方法后会关闭所有的非tab页面。
uni.navigateBack()
用于回退到之前的页面。
参数 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
delta | Number | 否 | 1 | 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 |
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
当然,更多的知识点和使用方法,在官网文档中才是最详细的,uniapp官网:uni-app官网