今日学习内容
- 安装uni-ui跟@uni-helper/uni-ui-types
- 配置pinia持久化
- 请求工具类的拦截器
- 请求工具类的请求函数
安装uni-ui跟@uni-helper/uni-ui-types
npm install -g cnpm --registry=https://registry.npmmirror.com
npm set registry https://registry.npmmirror.com
npm i -g pnpm
npm i @dcloudio/uni-ui
//配置ts类型
pnpm i -D @uni-helper/uni-ui-types
配置uni-ui自动导入
设置pinia持久化
1、新建stores/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'
2、在新建store的时候加上持久化的配置
import { defineStore } from 'pinia'
import { ref } from 'vue'
// 定义 Store
export const useMemberStore = defineStore(
'member',
() => {
// 会员信息
const profile = ref<any>()
// 保存会员信息,登录时使用
const setProfile = (val: any) => {
profile.value = val
}
// 清理会员信息,退出时使用
const clearProfile = () => {
profile.value = undefined
}
// 记得 return
return {
profile,
setProfile,
clearProfile,
}
},
// TODO: 持久化
{
//网页端的写法
// persist: true,
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
},
},
},
)
请求工具类的拦截器
配置拦截器并添加
import { useMemberStore } from "@/stores"
//api请求地址
const apiUrl = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'
//初始化拦截器配置
const httpInterceptor = {
//拦截前触发
invoke(options: UniApp.RequestOptions) {
//如果不是http请求开头的则需要拼接apiUrl
if (!options.url.startsWith('http')) {
options.url = apiUrl + options.url
}
//配置请求超时时间
options.timeout = 10 * 1000
//添加请求头
options.header = {
...options.header,
'source-client': 'miniapp'
}
//添加token
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
}
}
//添加拦截器 request uploadFile httpInterceptor是配置
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)
使用
<script setup lang="ts">
import { useMemberStore } from '@/stores'
import '@/utils/http'
const memberStore = useMemberStore()
const getData = () => {
uni.request({
method: 'GET',
url: '/category/top',
header: {
},
})
}
</script>
<template>
<view class="my">
<view>会员信息:{{ memberStore.profile }}</view>
<button @tap="
memberStore.setProfile({
nickname: '黑马先锋',
token: '123'
})
" size="mini" plain type="primary">
保存用户信息
</button>
<button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
<button @tap="getData()" size="mini" plain type="warn">发起请求</button>
</view>
</template>
<style lang="scss">
//
</style>
请求工具类的请求函数
import { useMemberStore } from '@/stores'
//api请求地址
const apiUrl = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'
//初始化拦截器配置
const httpInterceptor = {
//拦截前触发
invoke(options: UniApp.RequestOptions) {
//如果不是http请求开头的则需要拼接apiUrl
if (!options.url.startsWith('http')) {
options.url = apiUrl + options.url
}
//配置请求超时时间
options.timeout = 10 * 1000
//添加请求头
options.header = {
...options.header,
'source-client': 'miniapp',
}
//添加token
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
},
}
//添加拦截器 request uploadFile httpInterceptor是配置
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)
//配置请求函数
//step.1 先定义出与后端约定返回的数据格式
interface Data<T> {
code: string
msg: string
result: T
}
//step.2 定义出http 使用泛型
export const http = <T>(options: UniApp.RequestOptions) => {
//返回Promise
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
//step.3 响应成功
success(res) {
//如果状态码是2xx || 3xx 才会进入resolve
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
//清理用户信息并跳转到登录页
const memberStore = useMemberStore()
memberStore.clearProfile()
//跳转登录页
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
//其他错误,进行提示
uni.showToast({
title: (res.data as Data<T>).msg || '请求错误',
icon: 'none',
mask: true
})
reject(res)
}
},
//step.4 响应失败
fail(err) {
reject(err)
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试'
})
}
})
})
}
测试请求路径不存在
<script setup lang="ts">
import { useMemberStore } from '@/stores'
import { http } from '@/utils/http'
const memberStore = useMemberStore()
const getData = async () => {
const res = await http<string[]>({
method: 'GET',
url: '/category/top123',
header: {},
})
console.log(res)
}
</script>
<template>
<view class="my">
<view>会员信息:{{ memberStore.profile }}</view>
<button @tap="
memberStore.setProfile({
nickname: '黑马先锋',
token: '123',
})
" size="mini" plain type="primary">
保存用户信息
</button>
<button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
<button @tap="getData()" size="mini" plain type="warn">发起请求</button>
</view>
</template>
<style lang="scss">
//
</style>