项目的开发采用的是vscode,没有使用hbuildX开发。
1.请求封装
1.1拦截器封装,文件路径为@/src/interceptors/request.ts文件
/* eslint-disable no-param-reassign */
import qs from 'qs'
/* userStore中存储了token信息 */
import { useUserStore } from '@/store'
export type CustomRequestOptions = UniApp.RequestOptions & {
query?: Record<string, any>
} & IUniUploadFileOptions // 添加uni.uploadFile参数类型
// 请求域名地址
const baseURL = import.meta.env.VITE_SERVER_BASEURL
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: CustomRequestOptions) {
// 接口请求支持通过 query 参数配置 queryString
if (options.query) {
const queryStr = qs.stringify(options.query)
if (options.url.includes('?')) {
options.url += `&${queryStr}`
} else {
options.url += `?${queryStr}`
}
}
// 1. 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时
options.timeout = 10000 // 10s
// 3. 添加小程序端请求头标识
options.header = {
platform: 'mp-weixin', // 可选值与 uniapp 定义的平台一致,告诉后台来源
...options.header,
}
// 4. 添加 token 请求头标识
const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo
if (token) {
options.header.Authorization = `Bearer ${token}`
}
},
}
export const requestInterceptor = {
install() {
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
},
}
1.2完整请求代码,包括普通请求和文件上传请求
export const http = <T>(options: CustomRequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<IResData<T>>((resolve, reject) => {
uni.request({
...options,
dataType: 'json',
// #ifndef MP-WEIXIN
responseType: 'json',
// #endif
// 响应成功
success(res) {
// 状态码 2xx,参考 axios 的设计
if (res.status === 200) {
//将res.data返出去
resolve(res.data as IResData<T>)
} else if (res.status === 401) {
// 状态码为401,清理用户信息
userStore.clearUserInfo()
//跳转到登录页
uni.navigateTo({ url: '/pages/login/index' })
reject(res)
} else {
// 其他错误根据后端错误信息进行提示
uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,请检查网络',
})
reject(err)
},
})
})
}
// uni.uploadFile封装
export const uniFileUpload = <T>(options: CustomRequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<IResData<T>>((resolve, reject) => {
uni.uploadFile({
...options,
// 响应成功
success(res) {
// 状态码 2xx,参考 axios 的设计
if (res.status === 200) {
// 文件上传接口的rea.data的类型为string,这里转一下
const resData = JSON.parse(res.data) as IResData<T>
resolve(resData)
} else if (res.status === 401) {
// 状态码为401,清理用户信息
userStore.clearUserInfo()
//跳转到登录页
uni.navigateTo({ url: '/pages/login/index' })
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: '文件上传错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,请检查网络',
})
reject(err)
},
})
})
}
2.路由跳转
uniapp跳转有五种方式
2.1 uni.navigateTo(保留当前页面,跳转到应用其他页面,可以通过uni.navigateBack返回到原页面。TODO:不能跳转tabBar页面)
传递的参数在onLoad:function(option){}//这个option就是传过来的参数
uni.navigateTo({ url: `/pages/product/Detail?productId=${val.productId}&productName=${val.productName}` })
2.2 uni.navigateBack (关闭当前页面,返回上级页面或者多级页面,参数delta,必须为正整数)
可以通过getCurrentPages()方法获取页面栈,决定需要返回到哪一级,delta默认为1,返回到上一级,delta大于现有页面数,返回到首页
/* 假设在3级页面使用navigateBack,则返回到第一级 */
uni.navigateBack({ delta: 2 })
2.3 uni.redirectTo (关闭当前页面,跳转到其他页面,而uni.navigateTo是保留了当前页面)
uni.redirectTo({ url: '/pages/product/Apply' })
2.4 uni.reLaunch(关闭所有页面,跳转到其他页面)
uni.relaunch({ url: '/pages/product/Apply' })
2.5 uni.switchTab( 跳转tabBar页面专用,即导航栏之间的跳转,TODO:跳转前会关闭所有非导航栏页面)
uni.switchTab({ url: '/pages/product/Apply' })
3.uniapp的tabbar自定义,TODO:uniapp选取的ui框架为wot-desgin-uni
3.1 page.json里面tabBar属性的custom设置为true
3.2 在components目录下新建一个自定义tabbar组件
<template>
<wd-tabbar fixed v-model="tabbarStore.curIdx" bordered safeAreaInsetBottom placeholderuni @change="selectTabBar">
<block v-for="(item, index) in tabbarList" :key="item.path">
<wd-tabbar-item v-if="item.iconType === 'wot'" :icon="item.icon"></wd-tabbar-item>
<wd-tabbar-item v-else-if="item.iconType === 'unocss' || item.iconType === 'iconfont'" :title="item.text">
<template #icon>
<view h-20 w-20 :class="[item.icon, index === tabbarStore.curIdx ? 'is-active' : 'is-inactive']"> </view>
</template>
</wd-tabbar-item>
<wd-tabbar-item v-else-if="item.iconType === 'local'" :title="item.text">
<template #icon>
<image :src="item.icon" h-20 w-20 />
</template>
</wd-tabbar-item>
</block>
</wd-tabbar>
</template>
<script lang="ts" setup>
import { tabbarStore } from './tabbar'
import { tabBar } from '@/pages.json'
// unocss icon 默认不生效,需要在这里写一遍才能生效!注释掉也是生效的,但是必须要有!
// i-carbon-code
/* 将tabbar中list数据新增path属性 */
const tabbarList = tabBar.list.map((v: any) => ({ ...v, path: `/${v.pagePath}` }))
/* 切换tabbar时 TODO:function声明有变量提升*/
function selectTabBar({ value: index }: { value: number }) {
console.log(tabbarList, index, 'cjc')
const url = tabbarList[index].path
tabbarStore.setCurIdx(index)
uni.switchTab({ url })
}
onLoad(() => {
//原生tabbar未隐藏导致出现两个tabbar
// #ifdef APP-PLUS | H5
uni.hideTabBar({
fail(error) {
console.log('hideTabBar fail', error)
},
success(res) {
console.log('hideTabBar success', res)
},
})
})
</script>
<style lang="scss" scoped>
//
</style>
3.3 创建layout布局
<template>
<wd-config-provider :themeVars="themeVars">
<slot />
<xt-tabbar />
<wd-toast />
<wd-message-box />
</wd-config-provider>
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
colorTheme: 'red',
buttonPrimaryBgColor: '#07c160',
buttonPrimaryColor: '#07c160',
}
</script>
<style lang="scss" scoped></style>
3.4 tabbar的页面设置layout:'tabbar'
4.设置导航栏隐藏
"pages": [
{
"path": "pages/index/index",
"type": "home",
"layout": "tabbar",
"style": {
"navigationBarTitleText": "首页",
//第一种
"navigationStyle": "custom",
// 第二种
"app-plus": {
"titleNView":false
}
}
}
]
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
safeAreaInsets对象有四个属性top,bottom,left,right
5.uniapp 小程序支持分享微信和朋友圈
5.1首先导入onShareAppMessage(分享微信朋友),onShareTimeLine(分享朋友圈)
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
5.2 完善方法参数给定
/** 激活“分享给好友” */
onShareAppMessage((options: Page.ShareAppMessageOption): Page.CustomShareContent => {
console.log('options:', options)
return {
title: '这个是微信小程序',
desc: '采用unipp开发',
path: '/pages/index/index?id=xxx',
}
})
/** 激活“分享到朋友圈”, 注意:需要先激活“分享给好友” */
onShareTimeline((): Page.ShareTimelineContent => {
return {
title: '自定义分享标题',
query: 'a=1&b=2',
}
})
6.页面跳转navigator 类似html中的a标签
7.uniapp判断浏览器还是app
const type = uni.getSystemInfoSync().uniPlatform
console.log(type) // app就是app web就是浏览器
8.uniapp判断平台判断,微信小程序、H5、app
8.1 html进行判断
MP:小程序
<!-- #ifdef MP -->
<view> 小程序端 </view>
<!-- #endif -->
H5:H5端
<!-- #ifdef H5 -->
<view> H5端 </view>
<!-- #endif -->
APP:APP端
<!-- #ifdef APP-PLUS -->
<view> APP端 </view>
<!-- #endif -->
8.2 ts或者js中判断
MP:小程序
/*#ifdef MP*/
console.log('微信小程序端')
/*#endif*/
H5:H5端
/*#ifdef H5*/
console.log('H5端')
/*#endif*/
APP:APP端
/*#ifdef APP-PLUS*/
console.log('APP端')
/*#endif*/
8.3 css判断
MP:小程序
/*#ifdef MP*/
top:0;
/*#endif*/
H5:H5端
/*#ifdef H5*/
top:88rpx;
/*#endif*/
APP:APP端
/*#ifdef APP-PLUS*/
top:0;
/*#endif*/
9.获取系统信息uni.getSystemInfoSync
uniapp跳转 navigator标签类似标签
10.获取微信小程序胶囊位置信息uni.getMenuButtonBoundingClientRect()
10.自定义工具类全局注册
10.1 在App.vue注册全局工具类
<script>
import utilsFunc from './utils/index.ts'
export default {
onLaunch() {
console.log('App Launch')
},
onShow() {
console.log('App Show')
},
onHide() {
console.log('App Hide')
},
globalData(){
utils:utilsFunc
}
}
</script>
10.2 使用页面
const app = getApp()
onLoad(() => {
getUserInfo()
/*调用工具类方法*/
app.globalData.utils.currRoute()
})
11.不同页面之间数据传递
在使用数据页面进行监听uni.$on
传递页面$emit
12.微信小程序里面回去用户地址信息
uni.chooseAddress({
success: (res) => {
console.log(res, 'success')
},
fail: (res) => {
console.log(res, 'error')
},
})
同时需要在manifest.json里微信小程序模块进行配置
'mp-weixin': {
appid: VITE_WX_APPID,
setting: {
urlCheck: false,
},
usingComponents: true,
/* 获取地理位置信息配置 */
requiredPrivateInfos: [
'getLocation',
'onLocationChange',
'startLocationUpdateBackground',
'chooseAddress',
],
// __usePrivacyCheck__: true,
},
13.设置navBartitle
onLoad(() => {
/* 设置navBar文字 */
uni.setNavigationBarTitle({
title: '我爱cc',
})
})
14.小程序开发图表ucharts
15.生成全端二维码
16.tabbar切换时走的是v-show逻辑,因此刷新页面需要在页面周期函数onShow执行
17.拨打电话
uni.makePhoneCall({
phoneNumber: phone.value,
})
时间戳和hh:mm:ss
时分秒时间戳 -> hh:mm:ss
times(data) {
var time = Number(data);
var h = Math.floor(time / 3600);
var m = Math.floor((time % 3600) / 60);
var s = parseInt(time % 3600) % 60;
var hh = h < 10 ? "0" + h : h;
var mm = m < 10 ? "0" + m : m;
var ss = s < 10 ? "0" + s : s;
return hh + ":" + mm + ":" + ss;
},
hh:mm:ss -> 时分秒时间戳
time_to_sec(time) {
if (time !== null) {
var s = "";
var hour = time.split(":")[0];
var min = time.split(":")[1];
var sec = time.split(":")[2];
s = Number(hour * 3600) + Number(min * 60) + Number(sec);
return s;
}
},