0%

Vue3TypeScript(5) - 渲染404和登入頁面

1. 404 頁面實作

1.1. 新增views\404.vue

404.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div class="not-found">
<img src="../assets/404-error.png" alt="error">
<el-button class="goback" @click="$router.push('/')">The page you are looking for can’t be found. Go home by clicking here!</el-button>
</div>
</template>

<script lang="ts">
export default{

}
</script>

<style scoped>
.not-found {
width: 100%;
height: 100%;
overflow: hidden;
}
.not-found img {
width: 100%;
height: 100%;
}

.goback {
position: absolute;
z-index: 9999;
top: 80%;
left: 31%;
background-color: #fff;
color: rgb(48, 173, 211);
font-size: 1.5rem;
padding: 10px 30px;
border-radius: 5px;
outline: none;
border: none;
}
</style>

1.2. 修改router\index.ts

使用path/:catchAll(.*),只要是找不到的都會指向到這

1
2
3
4
5
6
7
8
9
10
11
12
const routes: Array<RouteRecordRaw> =[
{
path:"/",
name:"Login",
component:() => import("../views/Login.vue")
},
{
path:"/:catchAll(.*)",
name:"404",
component:() => import("../views/404.vue")
}
]

1.3. 最後結果

image-20220807005958868

2. 登入頁實作

在登入頁實作跳轉到後台介面過程,就必須與後端進行串接工作,而在現行主流前後端分離架構下,Mock Server 的準備是前端工程師開發流程非常重要的技能之一。之前就知道的Mock Server 工具是JSON-Server,這是一套運行在node js環境底下的工具。

今天想嘗試另一套「POSTMAN 」軟體,其中也支援這樣的功能,有機會再寫一篇介紹,使用方式與介紹先跳過…總之最後可以取得一個對外的URL提供使用。

2.1. 使用vite.config.ts進行代理

2.1.1. 修改\vite.config.ts

這邊增加了 server proxy,其中target 填上了POSTMAN產生的URL,rewrite部分也請記得改寫

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()
,
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server:{
proxy: {
'/api': {
target: 'https://c37e652f-46f8-4272-a694-85e33c3766b1.mock.pstmn.io',
changeOrigin: true,
rewrite: (path) => {
return path.replace('/api', '')
}
}
},
}
})

2.1.2. 修改src\views\Login.vue

實際上登入驗證的URL路徑為https://c37e652f-46f8-4272-a694-85e33c3766b1.mock.pstmn.io/login,因為我們使用了代理的關係,這邊填的URL就會以api為開頭:

1
const { data } = await axios.post("/api/login",formData);

Login.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<template>
<div class="container">
<h1>英語字典管理系統</h1>
<el-divider style="border-color:black" />
<el-row class="row" justify="center" style="margin-bottom:1.2rem;">
<div class="flex items-center">
<el-radio-group v-model="rdoRole">
<el-radio label="admin" size="large">管理員</el-radio>
<el-radio label="student" size="large">考生</el-radio>
</el-radio-group>
</div>

</el-row>
<el-row class="row" justify="center">
<el-col :span="12">
<el-form :label-position="labelPosition" label-width="100px" :model="formData" style="max-width: 560px">
<el-form-item label="帳號">
<el-input v-model="formData.account" placeholder="請輸入帳號" />
</el-form-item>
<el-form-item label="密碼">
<el-input v-model="formData.password" type="password" placeholder="請輸入密碼" show-password />
</el-form-item>
<div style="text-align:center">
<el-button @click="btnLogin" type="info" round
style="text-align:center;width:150px;font-size:1.5rem;background: #4A4A4A;padding:1.5rem">登入
</el-button>
</div>

</el-form>
</el-col>
</el-row>
</div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import axios from "axios";
const rdoRole = ref('admin')
const labelPosition = ref('top')

const formData = reactive({
account: '',
password: '',
})

const btnLogin = async () => {
console.log(rdoRole.value);
console.log(formData);

if (formData.account != '' && formData.password != '') {
console.log('ajax');
const { data } = await axios.post("/api/login",formData);
console.log(data);
}
else {
console.log('data 不完整');
}
}

</script>

<style scoped>
.container {
width: 800px;
margin: 10% auto;
}

h1 {
text-align: center;
font-size: 2rem;
}
</style>

2.1.3. 最後結果

觀查request console log ,的確有收到server 的response data

image-20220807114039287

觀查request URL值為http:127.0.0.1:5173/api/login,顯然代理成功,但還是對我感到好奇…實際上是怎麼做到的?有機會回來再了解一下

image-20220807114127268

2.2. 設定axios.defaults.baseURL

這個部分其實還有很多issue,就是如何做到產品階段設定開發階段設定吃不一樣的設定檔,這個部分後續花時間回來補一下。

先記錄一下簡單的版本,在有使用axios的地方,起頭就先宣告baseURL

src\view\Login.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import axios from "axios";
axios.defaults.baseURL="https://c37e652f-46f8-4272-a694-85e33c3766b1.mock.pstmn.io";
const rdoRole = ref('admin')
const labelPosition = ref('top')

const formData = reactive({
account: '',
password: '',
})

const btnLogin = async () => {
console.log(rdoRole.value);
console.log(formData);

if (formData.account != '' && formData.password != '') {
console.log('ajax');
const { data } = await axios.post("/login",formData);
console.log(data);
}
else {
console.log('data 不完整');
}
}

</script>

3. 伺服器回傳後,前端繼續驗證與處理

接續使用代理方式進行開發,下段程式碼透過localStorage先儲存回傳的token值,element plus 套件的ElMessage元件呈現登入成功的效果(toast notification)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const btnLogin = async () => {
console.log(rdoRole.value);
console.log(formData);

if (formData.account != '' && formData.password != '') {
const { data } = await axios.post("/api/login",formData);
const { token } = data.data;
console.log(data);
if(data.status == 'success')
{
localStorage.setItem("token",token);
// @ts-ignore
ElMessage({
showClose: true,
message: '登入成功.',
type: 'success',
});
router.push('/Main');
}
else{
alert('帳密錯誤');
}
}
else {
console.log('data 不完整');
}
}

效果如下:

image-20220807201545862

其中有一個ts-ignore要特別說明,因為稍早我們使用的是自動載入的方式,所以在開發階段的智能提示,會誤以為沒有進行import動作。要消除這個錯誤提示,我們可以在ElMessage上方加上ts-ignore寫法,錯誤就消失囉!

4. 參考資料