go17/vblog/web/README.md
2025-01-05 18:14:52 +08:00

325 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# web
Vblog 前端项目
## 清理模版代码
- 清理组件
- 清理样式
- 清理js文件
## 添加登录页面
- LoginPage.vue
```vue
<template>
<div>登录页面</div>
</template>
<script setup></script>
<style lang="css" scoped></style>
```
- 添加路有
```js
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/login',
name: 'login',
component: () => import('../views/common/LoginPage.vue'),
},
],
})
```
- App组件添加路由视图入口
```vue
<script setup></script>
<template>
<RouterView></RouterView>
</template>
<style scoped></style>
```
## 安装UI插件
https://gitee.com/infraboard/go-course/blob/master/day20/vue3-ui.md
```js
// 加载UI组件
import ArcoVue from '@arco-design/web-vue'
import '@arco-design/web-vue/dist/arco.css'
// 额外引入图标库
import ArcoVueIcon from '@arco-design/web-vue/es/icon'
app.use(ArcoVue)
app.use(ArcoVueIcon)
```
## Login Page开发
```vue
<template>
<div class="content">
<div class="login-container">
<div class="login-title">欢迎登录博客系统</div>
<div class="login-form">
<a-form size="large" :model="loginForm" @submit="handleSubmit">
<a-form-item
field="username"
hide-label
hide-asterisk
:rules="{ required: true, message: '请输入用户名' }"
>
<a-input
style="background-color: #fff;"
v-model="loginForm.username"
placeholder="请输入用户名"
>
<template #prefix>
<icon-user />
</template>
</a-input>
</a-form-item>
<a-form-item
style="margin-top: 12px"
field="password"
hide-label
hide-asterisk
:rules="{ required: true, message: '请输入密码' }"
>
<a-input-password
style="background-color: #fff;"
v-model="loginForm.password"
placeholder="请输入密码"
allow-clear
>
<template #prefix>
<icon-lock />
</template>
</a-input-password>
</a-form-item>
<a-form-item field="remember_me" hide-label hide-asterisk>
<a-checkbox style="margin-left: auto;" v-model="loginForm.remember_me" value="boolean"
>记住</a-checkbox
>
</a-form-item>
<a-form-item hide-label hide-asterisk>
<a-button type="primary" style="width: 100%;" html-type="submit">登录</a-button>
</a-form-item>
</a-form>
</div>
</div>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const loginForm = reactive({
username: '',
password: '',
remember_me: false,
})
const handleSubmit = (data) => {
if (data.errors === undefined) {
console.log(data.values)
}
}
</script>
<style lang="css" scoped>
.content {
height: 100%;
width: 100%;
justify-content: center;
align-items: center;
display: flex;
background-color: rgb(243, 238, 238);
}
.login-container {
width: 460px;
height: 320px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.3);
/* 增加透明度 */
border-radius: 15px;
backdrop-filter: blur(15px);
/* 增加模糊程度 */
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2);
}
.login-title {
margin-top: 12px;
margin-bottom: 12px;
font-size: 20px;
font-weight: 500;
color: var(--color-neutral-8);
}
.login-form {
padding: 20px;
height: 100%;
width: 100%;
}
</style>
```
## 对接后端
调用后端的Restful接口, 需要一个http客户端
- XMLHTTPRequest
- fetch
- axios: https://www.axios-http.cn/docs/intro
```shell
npm install axios
```
### 后端API
```js
export const client = axios.create({
baseURL: 'http://127.0.0.1:8080',
timeout: 3000,
})
```
```js
import { client } from './client'
export const LOGIN = (data) =>
client({
url: '/api/vblog/v1/tokens',
method: 'POST',
data: data,
})
```
### 页面使用
```js
const summitLoading = ref(false)
const handleSubmit = async (data) => {
if (data.errors === undefined) {
try {
summitLoading.value = true
await LOGIN(data.values)
} catch (error) {
console.log(error)
} finally {
summitLoading.value = false
}
}
}
```
```sh
Access to XMLHttpRequest at 'http://127.0.0.1:8080/api/vblog/v1/tokens' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
### 如何处理CORS
- 1. 服务端 允许跨越访问, 服务端需要配置一个CROS 中间件,返回 允许的 origin列表, 允许 origin localhost 访问
- 2. 前端使用代码, 前端先访问 -- proxy -- backend
推荐: 前端使用代理 , 最终的效果是 前端和后端部署在一起
前端如何配置代理: (vite)
```js
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx(), vueDevTools()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
proxy: {
'/api': 'http://localhost:8080',
},
},
})
```
http client在请求的时候不能指定baseURL: http://127.0.0.1:8080/api/vblog/v1/tokens,
```
http://localhost:5173/api/vblog/v1/tokens --> http://localhost:8080/vblog/v1/tokens
```
移除baseURL配置
```js
export const client = axios.create({
baseURL: '',
timeout: 3000,
})
```
### API 访问报错处理
添加一个响应拦截器来进行响应的处理
```js
// http 客户端配置一个拦截器
client.interceptors.response.use(
// 请求成功的拦截器
(value) => {
return value
},
// 请求失败
(error) => {
let msg = error.message
try {
msg = error.response.data.message
} catch (error) {
console.log(error)
}
Message.error(msg)
},
)
```
## 路由嵌套与布局
https://router.vuejs.org/zh/guide/essentials/nested-routes.html
```js
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
```