uni-app学习笔记

创建项目

通过HBuilderX创建

直接新建项目,选择vue的版本即可
Snipaste_2024-02-06_12-15-58

通过命令行创建

拉取vue3+ts的版本:
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
20240210210613

然后进入项目目录,下载依赖pnpm i(装了个pnpm)

记得加上appId

运行就用:npm run dev:mp-weixin

好好好,难道说我还要学个ts?

那这就学的太多了吧,先看看吧

用Vscode就直接导入就行了


vscode要安装些插件才能用着舒服,然后还要安装一个类型声明文件:

1
pnpm i -D @types/wechat-miniprogram @uni-helper/uni-app-types
  • 然后到manifest.json中配置小程序id
  • 到tsconfig.json中加上以下配置,用于语法检查
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    "types": [
    "@dcloudio/types",
    "@types/wechat-miniprogram",
    "@uni-helper/uni-app-types"
    ]
    },
    "vueCompilerOptions": {
    "nativeTags": [
    "block",
    "component",
    "template",
    "slot"
    ]
    },

熟悉案例

pages.json和tabBar案例

pages.json是配置页面路由,导航栏,tabBar等页面类信息

tabBar最少需要两项才有效

pages.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path" : "pages/my/my",
"style" :
{
"navigationBarTitleText" : "我的"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "white", // 头部字体颜色,只支持黑白
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#2B9939", // 全局头部背景色
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/tabs/send-fill.png",
"selectedIconPath": "static/tabs/send-fill.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/tabs/消息.png",
"selectedIconPath": "static/tabs/消息.png"
}
]
},
"uniIdRouter": {}
}

tabBar隐藏掉头部:

1
2
3
4
5
6
7
8
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom", // 自定义,就是隐藏掉头部那一块了
"navigationBarTextStyle": "white", // 更改头部字体的颜色,手机状态栏字体的颜色
"navigationBarTitleText": "首页"
}
},

但是由于现在手机都有刘海或者挖空,所以会出现这种情况:
20240216121053

就要进行适配:安全区域
20240216121205

通过小程序的api:const {safeAreaInsets} = uni.getSystemInfoSync()来获取屏幕边界到安全区域距离

再通过动态设置样式,来实现自适应

1
<view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"></view>

轮播图案例

  • 属性绑定还是:xx这种
  • 点击事件成了@tab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<template>
<swiper class="banner" indicator-dots circular :autoplay="true">
<swiper-item v-for="item in picture" :key="item.id">
<image @tap="onPreviewImage(item.url)" :src="item.url"></image>
</swiper-item>
</swiper>
</template>

<script>
export default {
data() {
return {
title: 'Hello uni-app',
// 轮播图
picture: [
{id: '1',url: "http://47.109.139.173:9000/food.guide/%E5%B0%8F%E5%9B%BE.jpg"},
{id: '2',url: "http://47.109.139.173:9000/food.guide/b1ba1c68-7b43-4c9f-9082-09bfcc9d8c57.jpg"}
]
}
},
onLoad() {

},
methods: {
// 这个语法是真离谱
onPreviewImage(url){
uni.previewImage({
urls: this.picture.map(v=>v.url),
current: url
})
}
}
}
</script>

<style>
.banner,
.banner image{
width: 750rpx;
height: 750rpx;
}
</style>

安装uni-ui组件库

安装命令

1
pnpm i @dcloudio/uni-ui

然后要配置自动导入,在pages.json中添加:

1
2
3
4
5
6
7
"easycom": {
"autoscan": true,
"custom": {
// uni-ui 规则如下配置
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},

配置uni-ui类型检测

  1. 安装
    1
    pnpm i -D @uni-helper/uni-ui-types
  2. 配置:在tsconfig.json的types中添加:
    1
    "@uni-helper/uni-ui-types"

状态管理

配置了pinia,这个不太好说,就直接看代码比较好

毕设和这个课同步进行哈哈哈操

请求和上传文件拦截器

这个直接拿来用应该没问题吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 添加拦截器
*/

import { useMemberStore } from '@/stores'

const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'

// 添加拦截器
const httpInterceptor = {
// 拦截前触发
invoke(options: UniApp.RequestOptions) {
// 拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 请求超时时间
options.timeout = 10000
// 添加小程序端请求头标识
options.header = {
// 保留原有的请求头参数
...options.header,
'source-client': 'miniapp',
}
// 添加token请求头标识
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
console.log(options)
},
}
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)

响应拦截器

请求成功,则提取出核心数据:res.data

请求失败:

  • 网络错误
  • 401,清理用户信息,跳转至登录界面
  • 其他错误,根据后端错误信息轻提示

也是放到http.ts文件内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 请求函数,返回promise对象
export const http = <T>(options: UniApp.RequestOptions) => {
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 请求成功
success(res) {
// 状态码2xx为请求成功
if (res.statusCode >= 200 && res.statusCode < 300) {
// as... 断言类型为指定的类型
resolve(res.data as Data<T>)
} else if (res.statusCode == 401) {
// 401错误
const userStore = useUserStore()
userStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
uni.showToast({
title: '请登录后进行操作',
icon: 'none',
})
reject(res)
} else {
// 其他错误
uni.showToast({
title: (res.data as Data<T>).msg || '请求错误',
icon: 'none',
mask: true,
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,请检查网络设置',
})
reject(err)
},
})
})
}

然后在需要发请求的地方引入:

1
2
3
4
5
6
7
8
9
10
import { http } from '@/utils/http'

// 这样发请求:
async function getData() {
const res = await http({
method: 'GET',
url: '/category/getAll'
})
console.log(res)
}

上面要改一下

组件封装

通用轮播图组件:轮播图组件需要在首页和分类页使用,封装成通用组件

  1. 准备组件
  2. 自动导入组件
  3. 添加组件类型声明

自动导入组件的配置,到pages.json中,按照uni-ui的自动导入配置,在下方写上一个这个:

1
2
// 以Xtx开头的组件, 在components文件夹中查找引入--需要重启服务
"^Xtx(.*)": "@/components/Xtx$1.vue"

然后直接引入,就可以了,不需要再写import

类型声明,在组件相同的目录添加components.d.ts

1
2
3
4
5
6
import XtxSwiper from './XtxSwiper.vue'
declare module 'vue' {
export interface GlobalComponents {
XtxSwiper: typeof XtxSwiper
}
}