[ Day24 ]
說明: 今天使用vue-router結合登入是否的判斷,在還沒登入的時候將網頁導到登入頁。
一、設定header.vue
<template>
<div>
<h1> {{ userName }} </h1>
<router-link v-if='notLogin' to='/login'>Login</router-link>
<a href="" v-if='!notLogin' @click.prevent="logout">Logout</a>
</div>
</template>
<script>
export default {
data() {
return {
userName:'',
notLogin:true
}
},
mounted() {
var userName = localStorage.getItem('userName')
console.log(userName)
this.userName = userName ? userName : '未登入'
this.notLogin = userName ? false : true
},
methods: {
logout() {
localStorage.removeItem('userName');
localStorage.removeItem('token');
this.$router.go(0)
}
}
}
</script>
<style>
</style>
這裡創建一個header組件,套用在SPA裡的每個組件,利用這個組件,我們可以判斷localstorage中是否有儲存
使用者資訊,如果沒有就顯示Login選項,如果有就顯示Logout的選項,並且顯示現在的使用者名稱。
要注意的是logout方法裡,在最後要呼叫this.$router.go(0) 這個方法,讓頁面重新整理,避免不更新的情況。
二、router設定
index.js
const router = new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
components: {
dafault: Hello,
nav: Header
}
},
{
path: '/login',
name: 'login',
components: {
dafault: Login,
nav: Header
}
}
]
})
在router的設定將原本的單一component組件,改為兩個組件components,並且賦予名稱。
其一是剛才設定的Header組件,給予nav的名稱。
三、router執行前的登入狀態判斷
index.js
router.beforeEach((to, from, next) => {
const isLogin = localStorage.getItem('token');
if (isLogin) {
next();
if(to.path == '/login') {
alert('已登入')
next('/');
}
} else {
if( to.path !== '/login' && to.path !== '/')
next('/login')
else
next()
}
})
這裡呼叫router的beforeEach方法,讓router組件要渲染前會判斷到此方法裡面的內容。
將token從localstorage中取出,如果有的話代表登入了,那麼直接轉到router組件內容裡,否則跳到登入頁。
四、app.vue主頁
<router-view name="nav" :key="key"></router-view>
<router-view name="dafault"></router-view>
這裡要注意的的是 router-view改用名稱判斷,是剛才在index.js 設定的router那幾組名稱。
另外nav的部分需要加上:key,用來判斷是哪個router的nav,避免不更新狀態。
五、Login.vue
<template>
<div>
<form method="post" class="loginForm" @submit.prevent>
帳號:<input type="text" v-model="user.username" />
<br>
密碼:<input type="password" v-model="user.password" />
<br>
<button class="btn" @click="submit">登入</button>
</form>
</div>
</template>
<script>
import request from "request";
const baseUrl = 'http://localhost:8102/api'
export default {
data() {
return {
user:{
username:'',
password:''
}
}
},
methods: {
submit() {
request.post(baseUrl + '/login',
{ form:this.user },
(err, res, body) => {
var rtnUser = JSON.parse(body)
if(rtnUser.token) {
localStorage.setItem('token', rtnUser.token)
localStora![https://ithelp.ithome.com.tw/upload/images/20201007/20110911fkRSwELind.png](https://ithelp.ithome.com.tw/upload/images/20201007/20110911fkRSwELind.png)ge.setItem('userName', rtnUser.username)
this.$router.push('/')
} else {
this.$router.push('/login')
this.$router.go(0)
}
})
}
}
}
</script>
Login.vue的組件,一樣透過proxy呼叫後端的login api,將表單的使用者資訊送過去後取回token 和 username。
六、後端passport 的 login api
app.post('/api/login', function(req, res, next){
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) { return res.json( { message: info.message }) }
req.logIn(user, function(err) {
if (err) return next(err);
user.token = req.session.id
return res.send(JSON.stringify(user));
})
})(req, res, next);
});
後端login api使用day10的passport local組件進行資料庫使用者判斷,
當確定使用者存在後,回傳使用者資訊以及sessionId當作token。
在這部分的實作還應該更一步加強為jwt之類的token認證,並且直接回傳此token,
但重點不在token實作所以跳過此部分。
七、畫面
[Day24結束]