Skip to content

Commit 1fcda90

Browse files
committed
添加 '34-用户共享状态封装'
1 parent 3bcc105 commit 1fcda90

1 file changed

+189
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
## 目标
2+
完成用户共享状态的基础封装。
3+
完成基础登录接口封装。
4+
## 背景
5+
为了保证登录后的用户信息的存储,我们需要先通过pinia进行封装用户共享状态管理器去管理用户的状态,方便我们后续的使用。
6+
## 开发
7+
在stores目录下创建一个user.ts的文件,用户存放用户的基本信息。如下:
8+
```typescript
9+
export interface UserInfo {
10+
id: number
11+
username: string
12+
nickname?: string
13+
avatar?: string
14+
email?: string
15+
mobile?: string
16+
signature?: string
17+
gender?: number
18+
realName?: string
19+
birthday?: string
20+
money?: number
21+
}
22+
23+
export const useUserStore = defineStore('user', () => {
24+
const userInfo = ref<UserInfo>()
25+
26+
const token = useAuthorization()
27+
28+
const setUserInfo = (info: UserInfo) => {
29+
userInfo.value = info
30+
}
31+
32+
const setToken = (val: string) => {
33+
token.value = val
34+
}
35+
36+
return {
37+
userInfo,
38+
setUserInfo,
39+
setToken,
40+
}
41+
})
42+
43+
```
44+
45+
## 登录接口封装
46+
接下来我们先来实现一下登录接口的封装,我们会将登录的接口封装到用户状态管理的代码逻辑中,方便我们后面使用和复用
47+
首先我们再src目录下创建一个api的文件夹用于存放我们所有与接口相关的类型和接口信息。
48+
然后我们在api下面创建一个user.ts的文件用于存放我们用户操作的一些接口信息,如下:
49+
50+
1. 首先将编写的类型放到user.ts的文件中,并从我们的stores/user.ts中采用导入的方式使用。
51+
52+
在 api/user.ts中
53+
```typescript
54+
export interface UserInfo {
55+
id: number
56+
username: string
57+
nickname?: string
58+
avatar?: string
59+
email?: string
60+
mobile?: string
61+
signature?: string
62+
gender?: number
63+
realName?: string
64+
birthday?: string
65+
money?: number
66+
}
67+
68+
```
69+
在stores/user.ts中
70+
```typescript
71+
import type { UserInfo } from '~/api/user'
72+
73+
export const useUserStore = defineStore('user', () => {
74+
const userInfo = ref<UserInfo>()
75+
76+
const token = useAuthorization()
77+
78+
const setUserInfo = (info: UserInfo) => {
79+
userInfo.value = info
80+
}
81+
82+
const setToken = (val: string) => {
83+
token.value = val
84+
}
85+
86+
return {
87+
userInfo,
88+
setUserInfo,
89+
setToken,
90+
}
91+
})
92+
93+
```
94+
95+
2. 实现开发全局代理
96+
97+
在我们真实开发的过程中,前后端分离在H5端一般没有特殊处理的话可能会出现跨域的问题,为了防止这种问题的发生我们可以在vite.config.ts中配置代理处理为同源协议,这样就可以避免我们在开发阶段出现跨域的问题。
98+
首先我们在.env.development中添加我们需要做代理的链接(这里使用我们的mock地址作为演示)
99+
```shell
100+
VITE_APP_BASE_URL=https://mock.28yanyu.cn/mock/637af0d4080d2f1284a9e77b
101+
```
102+
我们在真正的开发环境中使用的并不是我们mock的接口数据,例如我们生产环境下的api的地址为`https://www.baidu.com/api`,那么我们在.env.production里面配置如下:
103+
```shell
104+
VITE_APP_BASE_URL=https://www.baidu.com/api
105+
```
106+
然后在types/env.d.ts中添加对应类型
107+
```typescript
108+
interface ImportMetaEnv {
109+
readonly VITE_APP_BASE: string
110+
readonly VITE_APP_BASE_API: string
111+
+ readonly VITE_APP_BASE_URL: string
112+
}
113+
114+
```
115+
最后我们在vite.config.ts中实现代理的功能
116+
```typescript
117+
import { defineConfig, loadEnv } from 'vite'
118+
119+
export default defineConfig(({ mode }) => {
120+
const env = loadEnv(mode, process.cwd())
121+
return {
122+
...,
123+
server: {
124+
proxy: {
125+
[env.VITE_APP_BASE_API]: {
126+
target: env.VITE_APP_BASE_URL,
127+
changeOrigin: true,
128+
ws: false,
129+
rewrite: path => path.replace(new RegExp(`^${env.VITE_APP_BASE_API}`), ''),
130+
},
131+
},
132+
},
133+
}
134+
}
135+
```
136+
137+
3. 在api/user.ts中实现登录接口测试代理
138+
139+
前面我们已经配置好对应的mock接口地址,接下来我们来测试一下登录的mock接口
140+
```shell
141+
export const userLoginUrl = '/user/login'
142+
export interface UserAccountLoginParams {
143+
username: string
144+
password: string
145+
captcha?: string
146+
}
147+
export interface UserMobileLoginParams {
148+
mobile: string | number
149+
captcha: string
150+
}
151+
152+
export interface UserLoginResult {
153+
token: string
154+
}
155+
156+
export const userLoginApi = (params: UserAccountLoginParams | UserMobileLoginParams) => {
157+
return usePost<UserMobileLoginParams | UserAccountLoginParams, UserLoginResult>(userLoginUrl, params)
158+
}
159+
160+
```
161+
在stores/user.ts中注册使用并进行导出
162+
```typescript
163+
const login = async (params: UserMobileLoginParams | UserAccountLoginParams) => {
164+
const { data } = await userLoginApi(params)
165+
if (data?.token)
166+
setToken(data.token)
167+
}
168+
```
169+
我们在登录页面进行测试是否可用
170+
```vue
171+
<script lang="ts" setup>
172+
const userStore = useUserStore()
173+
const onConfirmLogin = async () => {
174+
await userStore.login({
175+
username: '',
176+
password: '',
177+
})
178+
}
179+
</script>
180+
<template>
181+
<n-button
182+
type="primary"
183+
block secondary
184+
strong @click="onConfirmLogin">
185+
{{ $t("login.login") }}
186+
</n-button>
187+
</template>
188+
```
189+
可以正常请求通数据

0 commit comments

Comments
 (0)