# 網頁實作(1) 登入頁面
###### tags: `VueJS` `golang`
最近開始想嘗試製作看看網頁,雖然沒有什麼方向,但先從大多數網站都有的登入開始製作看看吧!
首先登入頁面一般都會有帳號跟密碼的輸入,由於本人不是前端專業,就先簡單用bootstrap+Vue弄一個出來吧!
如果不知道怎麼安裝及使用Vue的話請走[這邊](https://hackmd.io/@JiFang/HyCMXJ9tu)
## 起步
```htmlembedded=
<!-- components/Login.vue -->
<template>
<div>
<b-form @submit="onSubmit">
<b-form-group
class="input-block"
label="Account"
label-for="input-1"
valid-feedback="ok!"
:invalid-feedback="invalidFeedback"
>
<b-form-input
id="input-1"
v-model="user.username"
placeholder="Your username"
:state="usernameState"
required
></b-form-input>
</b-form-group>
<b-form-group class="input-block" label="Password" label-for="input-2">
<b-form-input
id="input-2"
v-model="user.password"
type="password"
placeholder="Your password"
required
></b-form-input>
</b-form-group>
<b-button type="submit" variant="primary">Submit</b-button>
</b-form>
<router-link id="signUp" to="/">Or sign up here!</router-link>
</div>
</template>
```
```css=
.input-block {
text-align: left;
}
#signUp {
font-size: 12px;
}
</style>
```
畫面會長這樣

其實外層有多包一層,讓它看起來好看一點,不過不贅述。
## 綁定資料
### 1. 輸入綁定
首先要先把輸入的資料跟js綁在一起
```javascript=
export default {
data() {
return {
user: {
username: "",
password: "",
},
loginStatus: "",
};
},
```
再來我想要判斷帳號輸入是否超過4個字,可以透過bootstrap來做
```javascript=
computed: {
invalidFeedback() {
return "Enter at least 4 characters.";
},
usernameState() {
return this.user.username.length > 3;
},
},
```
這樣invalidFeedback可以判斷輸入的字數並給予提示,usernameState可以給框框一個紅色警示外框。
### 2. 方法綁定
最後按下submit的時候我們必須要跟後端做串接,需要使用到Vue官方推薦使用的套件`axios`來做API的互動。
#### 安裝
```bash=
npm install --save axios vue-axios
```
在`main.js`中導入
```javascript=
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
```
這樣就可以使用了!繼續接下去實作!
```javascript=
methods: {
async onSubmit(event) {
event.preventDefault();
await this.axios
.post("http://localhost:5050/api/login", JSON.stringify(this.user))
.then((response) => {
this.$router.push("/");
this.loginStatus = response.status;
})
.catch((error) => {
this.loginStatus = error.response.status;
alert("Wrong username or password!");
this.user.password = "";
});
},
},
```
其實看一看上面的方法就類似爬蟲去抓API的概念,只是我們把它放到網頁上而已(**而且可以直接異步操作!**)。
另外有看到`this.$router`是在成功登入後協助我們導向到首頁的機制。
之後應該會實作成功登入後導向到前一頁,比較符合UX。
這個localhost:5050是我這邊已經實作了一個簡單的後端,程式碼也不難,是使用golang的gin實作。
```go=
import (
"net/http"
"github.com/gin-gonic/gin"
)
type LoginCommand struct {
Username string `json:"username"`
Password string `json:"password"`
}
func Login(ctx *gin.Context) {
var loginCmd LoginCommand
ctx.BindJSON(&loginCmd)
if loginCmd.Username == "max" && loginCmd.Password == "123" {
ctx.JSON(http.StatusOK, gin.H{"status": "ok"})
} else {
ctx.JSON(http.StatusUnauthorized, gin.H{"status": "wrong auth"})
}
}
```
## 遇到的問題
當前端在跟後端溝通時,會發生一個叫做[CORS](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS)的錯誤
在gin的框架中可以使用middleware來解決這個問題。
```go=
package middleware
import "github.com/gin-gonic/gin"
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
```
寫好之後再router添加middleware即可
```go=
router := gin.Default()
router.Use(middleware.CORSMiddleware())
```
## 心得
說真的看了上面的一堆東西之後,前端的功好像比後端來得多...只是本人又非前端專業,可能會寫得不太好。
下次來實作cookie登入,搭配後端回傳,順便建立一個簡單的資料庫來玩玩!