1.pages.json和tabBar案例
1.1 文件介绍
1.2 做一下pages.json的路由和tabbar配置:
{
"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": "#1bac9b",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
// 修改选中时候的颜色
"selectedColor": "#1bac9b",
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"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": {}
}
效果:
1.3总结和注意事项:
2. uni-app和原生小程序开发的区别
2.1 属性绑定的书写区别
2.2 事件绑定的区别
2.3 支持Vue常用指令
大致:
2.4 轮播图案例
<template>
<!-- 写结构: -->
<swiper class="banner" indicator-dots :autoplay="false">
<swiper-item v-for="item in pitures" :key="item.id">
<!-- 以前是bindtap,现在@就好了(点击绑定自定义事件) -->
<image @tap="onPreviewImage(item.URL)" :src="item.URL"></image>
</swiper-item>
</swiper>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
pitures: [
{ id: '1', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_1.jpg' },
{ id: '2', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_2.jpg' },
{ id: '3', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_3.jpg' },
{ id: '4', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_4.jpg' }
]
};
},
onLoad() {},
methods: {
onPreviewImage(URL) {
// 测试绑定事件是否成功
console.log(URL); //点击对应图片,成功在控制台输出图片url
// 使用微信的官方预览方法
// 定义一个形参v
wx.previewImage({
//或者可以写成uni.previewImage
// 返回v中的url,将其提取到一个全新的数组里
urls: this.pitures.map((v) => v.URL),
current: URL
});
}
}
};
</script>
<style>
.banner,
.banner image {
width: 750rpx;
height: 750rpx;
}
</style>
3.使用命令行创建uni-app项目
好处:不用依赖HBuilderX,可以在自己喜欢的编辑器上编辑(如cursor)
4. 使用vsCode开发uni-app项目
5. 正式开始实战
克隆命令:
E:\DeskTop\XtxProject>git clone git.itcast.cn/heimaqiandu… heima-shop
结果:
6.1 基础架构-使用uni-ui组件库
使用easycom自动导入组件
使用easycom自动导入
6.2.使用uni-helper/uni-ui-types
官方并没有提供对应的类型说明文字,所以使用这个拓展包,用起来更加的方便和放心
6.3 总结:
7 状态管理(小程序端Pinia持久化)
回顾一下Pinia的作用:
7.1 在小程序段使用persistent实现永久存储
因为网页端API和小程序端API有差异,所以我们干脆使用兼容多端的uni的API
8 基础架构
8.1 数据交互-请求工具的封装
8.1.1 拦截器的封装
STRING:拦截器api的名称
object:拦截后的行为
拦截器拦截之后需要实现的四个核心业务:
用户登录后获取token
8.1.2 请求函数的封装
8.1.2.1 http.ts文件中添加拦截器
// 添加拦截器
// 拦截request请求
// 拦截uploadFile文件上传
import { useMemberStore } from '@/stores';
// TODO;
// 非http开头需拼接地址
// 请求超时
// 添加小程序端请求头标识
// 添加token请求头标识
const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net';
// 添加拦截器
// 拦截request请求
const httpInterceptor = {
// 拦截前触发
// 注意:在ts项目中参数需要指定类型,所以要在形参options:后指定
invoke(options: UniApp.RequestOptions) {
// 1.非http开头的地址需要拼接地址,否则就是完整的
options.url = baseURL + options.url;
if (!options.url.startsWith('http')) {
}
// 2.请求超时,默认最大时间为60s(我们这改成10s)
options.timeout = 10000;
console.log(options);
// 3.添加小程序端请求头标识
options.header = {
...options.header,
'source-client': 'miniapp'
};
// 4. 添加token请求头标识
const meberStore = useMemberStore();
const token = meberStore.profile?.token;
if (token) {
options.header.Authorization = token;
}
console.log(options);
}
};
// ⭐ 必须导出一个函数给 main.ts 调用
export function setupInterceptor() {
uni.addInterceptor('request', httpInterceptor);
uni.addInterceptor('uploadFile', httpInterceptor);
}
8.1.2.2 在main.ts中注册拦截器
8.1.2.3 最终测试结果
8.1.3 封装Promis请求功函数
回顾一下promise和axios
回顾一下promise的固定两个参数
8.1.3.2 成功resolve
// 请求函数
// @param UniApp.RequestOptions
// @return Promise
// TODO:
// 1.返回Promisre对象
// 2.请求成功
// 2.1提取核心数据 res.data
// 2.2 添加类型,支持泛型
// 3.请求失败
// 3.1网络错误->提示用户换网络
// 3.2 401错误->清理用户信息,跳转到登录页
// 3.3 其他错误->根据后端错误信息轻提示
interface Data<T> {
code: string;
msg: string;
// 因为result的长度不固定,所以给她使用泛型
result: T;
}
// 实现请求函数的封装并返回一个对象
export const http = <T>(options: UniApp.RequestOptions) => {
// 返回一个Promis对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 2.请求成功
success(res) {
// 2.1提取核心数据(as Data<T>类型断言)
// 数据断言:简单来说,就是覆盖 TS 自动类型推断。
resolve(res.data as Data<T>);
}
});
});
};
8.1.3.4 失败reject
实现代码:
// 请求函数
// @param UniApp.RequestOptions
// @return Promise
// TODO:
// 1.返回Promisre对象
// 2.请求成功
// 2.1提取核心数据 res.data
// 2.2 添加类型,支持泛型
// 3.请求失败
// 3.1网络错误->提示用户换网络
// 3.2 401错误->清理用户信息,跳转到登录页
// 3.3 其他错误->根据后端错误信息轻提示
interface Data<T> {
code: string;
msg: string;
// 因为result的长度不固定,所以给她使用泛型
result: T;
}
// 实现请求函数的封装并返回一个对象
export const http = <T>(options: UniApp.RequestOptions) => {
// 返回一个Promis对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 2.请求成功
success(res) {
// 通过状态码查看是否成功
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1提取核心数据(as Data<T>类型断言)
// 数据断言:简单来说,就是覆盖 TS 自动类型推断。
resolve(res.data as Data<T>);
}
// 3.2 401错误->清理用户信息,跳转到登录页
else if (res.statusCode === 401) {
const memberStore = useMemberStore();
// 清理数据
memberStore.clearProfile();
// 跳转到登录页
uni.navigateTo({
url: '/pages/login/login'
});
// uni.redirectTo({ url: '/pages/login/login' });
reject(res);
} else {
// 3.3 其他错误->根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误'
});
// 标记为失败
reject(res);
}
},
// 响应失败(用户网络有误)
fail(err) {
// 轻提示
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试吧!'
});
reject(err);
}
});
});
};
9 自定义导航栏
9.1 安全区域
使用uni的getSystemInfoSync()的api来实现不同机型自动适配的安全区域
结果:
iphone6:
iphone15pro: