目录
项目架构
uni-app小兔鲜儿电商项目架构
小兔鲜儿电商课程安排
创建uni-app项目
1.通过HBuilderX创建
2.通过命令行创建
pages.json和tabBar案例
uni-app和原生小程序开发区别
用VS Code开发uni-app项目
拉取小兔鲜儿项目模板代码
基础架构–引入uni-ui组件库
操作步骤
安装类型声明文件
配置类型声明文件
基础架构–小程序端Pinia持久化、
持久化存储插件
网页端持久化 API
多端持久化 API
参考代码
基础架构–uni.request请求封装
基础架构–请求和上传文件拦截器
基础架构–封装Promise请求函数
项目架构
uni-app小兔鲜儿电商项目架构
小兔鲜儿电商课程安排
创建uni-app项目
创建uni-app项目
uni-app支持两种方式创建项目:
1.通过HBuilderX创建
1.1下载安装HbuilderX编辑器
1.2通过HbuilderX创建uni-app vue3项目
1.3安装uni-app vue3编译器插件
1.4编译成微信小程序端代码
1.5开启服务端口
小技巧分享:模拟器窗口分离和置顶
两者关系
2.通过命令行创建
通过命令行创建(不必依赖HBuilderX)
命令行创建uni-app项目:
vue3+ts版:
npx degit dcloudio/uni-preset-vue#vite-ts 项目名称
创建其他版本可查看:uni-app 官网https://uniapp.dcloud.net.cn/quickstart-cli.html
编译和运行uni-app项目:
- 安装依赖
pnpm install
- 编译成微信小程序
pnpm dev:mp-weixin
- 导入微信开发者工具
温馨提示: 在 manifest.json
文件添加小程序 appid
方便真机预览
pages.json和tabBar案例
我们先来认识 uni-app 项目的目录结构。
├─pages 业务页面文件存放的目录
│ └─index
│ └─index.vue index页面
├─static 存放应用引用的本地静态资源的目录(注意:静态资源只能存放于此)
├─unpackage 非工程代码,一般存放运行或发行的编译结果
├─index.html H5端页面
├─main.js Vue初始化入口文件
├─App.vue 配置App全局样式、监听应用生命周期
├─pages.json **配置页面路由、导航栏、tabBar等页面类信息**
├─manifest.json **配置appid**、应用名称、logo、版本等打包信息
└─uni.scss uni-app内置的常用样式变量
用于配置页面路由、导航栏、tabBar 等页面类信息
{
"pages": [ //页面路径及窗口表现
{
"path": "pages/index/index", //页面路径
"style": { //页面样式
"navigationBarTitleText": "首页" //导航栏的标题文字
}
},
{
"path": "pages/my/my",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"globalStyle": { //全局页面样式
"navigationBarTextStyle": "white", //导航栏标题颜色只支持black/white
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#27ba9b", //导航栏背景颜色
"backgroundColor": "#F8F8F8"
},
"tabBar": { //底部tab
"list": [{ //tab列表
"pagePath": "pages/index/index", //页面路径
"text": "首页", //tab的文字
"iconPath": "static/tabs/home_default.png", //图片路径
"selectedIconPath": "static/tabs/home_selected.png" //选中图片的路径
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/tabs/user_default.png",
"selectedIconPath": "static/tabs/user_selected.png"
},
]
},
"uniIdRouter": {}
}
uni-app和原生小程序开发区别
每个页面是一个.vue文件,数据绑定及事件处理同Vue.js规范:
1.属性绑定src="{{ url }}"升级成:src="url"
2.事件绑定bindtap="eventName"升级成@tap="eventName",支持()传参
3.支持Vue常用指令v-for、v-if、v-show、v-model等
温馨提示:调用接口能力,建议前缀wx替换为uni,养成好习惯,这样支持多端开发。
<style></style>
样式不需要写scoped
生命周期分为三部分:应用生命周期(小程序),页面生命周期(小程序),组件生命周期(Vue)
<template>
<!--indicator-dots 是否显示面板指示点 :autoplay 是否自动切换 circular 是否采用衔接滑动,即播放到末尾后重新回到开头-->
<swiper indicator-dots :autoplay="false" circular>
<swiper-item class='banner' v-for="item in picurls" :key='item.id'>
<image :src="item.url" @tap='onImageChange(item.url)' mode=""></image>
</swiper-item>
</swiper>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
picurls: [{
id: 1,
url: 'https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1691600400&t=923ddedd0e2c4310685b4603e1d3b3c3'
}, {
id: 2,
url: 'https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1691600400&t=923ddedd0e2c4310685b4603e1d3b3c3'
}, {
id: 3,
url: 'https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1691600400&t=923ddedd0e2c4310685b4603e1d3b3c3'
}, {
id: 4,
url: 'https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1691600400&t=923ddedd0e2c4310685b4603e1d3b3c3'
}, {
id: 5,
url: 'https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1691600400&t=923ddedd0e2c4310685b4603e1d3b3c3'
}]
}
},
onLoad() {
},
methods: {
onImageChange(url) {
console.log(url);
uni.previewImage({ //在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作。
urls: this.picurls.map(v => v.url), //需要预览的图片链接列表。2.2.3 起支持云文件ID。
current: url // 当前显示图片的链接
})
}
}
}
</script>
<style>
.banner,
.banner image {
width: 750rpx;
height: 750rpx;
}
</style>
用VS Code开发uni-app项目
用VS Code开发uni-app项目
为什么选择VS Code?
- HbuilderX对TS类型支持暂不完善
- VS Code对TS类型支持友好,熟悉的编辑器
用 VS Code 开发配置
- 安装 uni-app 插件
- uni-create-view :快速创建 uni-app 页面
- uni-helper uni-app :代码提示
- uniapp 小程序扩展 :鼠标悬停查文档
- TS 类型校验
- 安装类型声明文件
pnpm i -D @types/wechat-miniprogram @uni-helper/uni-app-types
- 配置
tsconfig.json
- 安装类型声明文件
- JSON 注释问题
- 设置文件关联,把
manifest.json
和pages.json
设置为jsonc
- 设置文件关联,把
// 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"]
}
注意:原配置 experimentalRuntimeMode
现无需添加
温馨提示:
VS Code
可通过快捷键Ctrl + i
唤起代码提示。
拉取小兔鲜儿项目模板代码
拉取小兔鲜儿项目模板代码
项目模板包含:目录结构,项目素材,代码风格。
git clone http://git.itcast.cn/heimaqianduan/erabbit-uni-app-vue3-ts.git
heima-shop
注意事项
- 在
manifest.json
中添加微信小程序的appid
基础架构–引入uni-ui组件库
操作步骤
安装 uni-ui 组件库https://uniapp.dcloud.net.cn/component/uniui/quickstart.html#npm%E5%AE%89%E8%A3%85
pnpm i @dcloudio/uni-ui
配置自动导入组件
// pages.json
{
// 组件自动导入
"easycom": {是否开启自动导入
"autoscan": true,
"custom": {
// 提取uni的后缀名替换到$1找到正确文件
// uni-ui 规则如下配置 // [!code ++]
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" // [!code ++]
}
},
"pages": [
// …省略
]
}
安装类型声明文件
pnpm i -D @uni-helper/uni-ui-types
配置类型声明文件
// tsconfig.json
{
"compilerOptions": {
"types": [
"@dcloudio/types",
"@uni-helper/uni-app-types", // [!code ++]
"@uni-helper/uni-ui-types" // [!code ++]
]
}
}
基础架构–小程序端Pinia持久化、
说明:项目中 Pinia 用法平时完全一致,主要解决持久化插件兼容性问题。
持久化存储插件
持久化存储插件: pinia-plugin-persistedstatehttps://prazdevs.github.io/pinia-plugin-persistedstate/guide/config.html#storage
插件默认使用 localStorage
实现持久化,小程序端不兼容,需要替换持久化 API。
网页端持久化 API
// 网页端API
localStorage.setItem()
localStorage.getItem()
多端持久化 API
// 兼容多端API
uni.setStorageSync()
uni.getStorageSync()
参考代码
// stores/modules/member.ts
export const useMemberStore = defineStore(
'member',
() => {
//…省略
},
{
// 配置持久化
persist: {
// 调整为兼容多端的API
storage: {
setItem(key, value) {
uni.setStorageSync(key, value) // [!code warning]
},
getItem(key) {
return uni.getStorageSync(key) // [!code warning]
},
},
},
},
)
基础架构–uni.request请求封装
基础架构–请求和上传文件拦截器
uniapp 拦截器: uni.addInterceptorhttps://uniapp.dcloud.net.cn/api/interceptor.html
接口说明:接口文档https://www.apifox.cn/apidoc/shared-0e6ee326-d646-41bd-9214-29dbf47648fa/doc-1521513
实现步骤
- 基础地址
- 超时时间
- 请求头标识
- 添加 token
// src/utils/http.ts
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 = {
...options.header,
'source-client': 'miniapp',
}
// 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)
基础架构–封装Promise请求函数
实现步骤
- 返回 Promise 对象
- 成功 resolve
- 提取数据
- 添加泛型
- 失败 reject
- 401 错误
- 其他错误
- 网络错误
参考代码
/**
* 请求函数
* @param UniApp.RequestOptions
* @returns Promise
* 1. 返回 Promise 对象
* 2. 获取数据成功
* 2.1 提取核心数据 res.data
* 2.2 添加类型,支持泛型
* 3. 获取数据失败
* 3.1 401错误 -> 清理用户信息,跳转到登录页
* 3.2 其他错误 -> 根据后端错误信息轻提示
* 3.3 网络错误 -> 提示用户换网络
*/
type Data<T> = {
code: string
msg: string
result: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<Data<T>>((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<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>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}
请求函数–请求成功提取数据和设置类型
基础架构–封装Promise请求函数
请求函数–获取数据失败
- uni.request的success回调函数只是表示服务器响应成功,没处理响应状态码,业务中使用不方便
- axios函数是只有响应状态码是2xx才调用resolve函数,表示获取数据成功,业务中使用更准确