這篇文章我們結合vue和vue-router來說一下如何實現用戶的登錄,退出,和cookies
先回憶一下之前《vue-router—14案例:模擬登錄跳轉》這篇文章
1. vue-router—14案例:模擬登錄跳轉
首先封裝一下插件(關於爲什麼這麼封裝,爲什麼會有install,可以參考這篇博文https://www.cnblogs.com/mengfangui/p/9046525.html)
utils.js
/**
* Vue的插件,用來獲取和設置localStorage存儲
**/
let local = {
save (key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
fetch (key) {
return JSON.parse(localStorage.getItem(key)) || {}
}
}
export default {
install: function (vm) {
vm.prototype.$local = local
}
}
然後在main.js中use
然後在router.js中全局路由鉤子中判斷
router.beforeEach((to, from, next) => {
let b1 = to.matched.some(item => item.meta.login)
if(b1) { // matched這個字段包含了所有的相關的節點,假如有任何一個節點有{login:true}
// 獲取到緩存裏面的用戶的字段
let info = router.app.$local.fetch("miaov")
if(info.login){ //如果是已經登錄狀態
next();
}else{ //如果是登出狀態
// 此處跳轉到登錄界面,並且新增加一個字段,記錄用戶一開始想去的路由
router.push({
path: '/login',
query: {
redirect: to.path.slice(1)
}
})
}
}else{ // matched這個字段包含了所有的相關的節點,沒有任何一個節點包含login,那麼就不用管了
next()
}
})
現在就到了登錄界面login.vue
<template>
<div class="login">
<div class="login-box">
<h2>登錄</h2>
<form @submit.prevent='sendLogin' autocomplete="off">
<div><input placeholder="請輸入用戶名" type="text" name="user" ref="userInput" /></div>
<div><input placeholder="請輸入密碼" type="password" name="password" /></div>
<div class="login-btn"><input type="submit" value="一鍵登入" /></div>
</form>
<div class="back-index">
<router-link to="/">首頁>>></router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'login',
data () {
return {}
},
methods: {
sendLogin () {
// 點擊登錄
let userName = this.$refs.userInput.value;
// 向緩存中保存用戶信息
this.$local.save("miaov", {
login: true,
userName: userName
})
// 獲取在全局路由鉤子中記錄的用戶一開始想去的路由界面
let redirect = this.$route.query.redirect
// 如果沒有記錄,那就默認進project這個路由界面
if(!redirect){
redirect = 'project'
}
// 跳轉路由
this.$router.push({
path: '/'+redirect
})
}
}
}
</script>
<style>
</style>
接下來就是home.vue這塊
如果從緩存中獲取到信息,則就顯示用戶的姓名和圖標,如果沒有,那麼顯示登錄兩個字
<template>
<div class="main">
<div class="home-header">
<img src="../assets/miaov.png" alt="">
<div class="portrait" :class={portraitLogin:isLogin}>
<router-link v-if="!isLogin" to="/login" tag="span">登錄</router-link>
<img v-if="isLogin" src="../assets/portrait.png" alt="">
</div>
</div>
<div class="phrase">
一起學習Vue-router
</div>
<div class="btns">
<router-link to="/project" tag="div" class=" trans">我的項目</router-link>
<router-link to="/doc" tag="div" class=" trans">我的文檔</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'home',
data () {
return {
isLogin: false
}
},
created(){
// 拿到登錄信息
let info = this.$local.fetch('miaov')
this.isLogin = info.login;
}
}
</script>
<style>
</style>
下來是這塊的顯示以及退出
header,vue
<template>
<div class="clearFix el-menu--dark">
<ul class="el-menu menu-horizontal el-menu--dark el-menu--horizontal header-nav" >
<router-link to="/" class="el-menu-item logo" exact tag="li">
<img src="../assets/miaov.png">
</router-link>
<router-link to="/project" class="el-menu-item" tag="li" >
<i class="fa fa-home"></i>
我的項目
</router-link>
<router-link to='/workbench' class="el-menu-item" tag="li">
<i class="fa fa-code"></i>
工作臺
</router-link>
<router-link to="/doc" class="el-menu-item" tag="li">
<i class="fa fa-book"></i>
文檔
</router-link>
</ul>
<div class="user-info-box" v-show="isLogin">
<div class="el-submenu__title">
<img src="../assets/portrait.png">
<span>{{userName}}</span>
</div>
<div class="header-menu">
<ul class="menu-nav">
<li class="el-menu-item" @click="loginOut">登出</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Header',
data () {
return {
userName: '',
isLogin: false
}
},
created(){
let info = this.$local.fetch("miaov")
this.isLogin = info.login;
this.userName = info.userName
},
methods: {
loginOut(){
this.$local.save("miaov", null)
this.$router.push("/login")
}
}
}
</script>
<style>
</style>
2.實際項目
下來分析一下我們的協同項目中登錄登出是怎麼寫
login.vue
<template>
<div class="login">
<div>
<div class="hd-logo"></div>
<div class="header">{{this.tenantName}}3D雲設計平臺</div>
<el-form :model="login">
<div style="width: 324px;margin: auto;">
<el-row>
<el-col>
<el-input v-model="login.email" placeholder="請輸入郵箱賬號"></el-input>
</el-col>
</el-row>
<el-row>
<el-col>
<el-input type="password" v-model="login.password" placeholder="請輸入密碼"></el-input>
</el-col>
</el-row>
<el-row v-if="isValidateCodePicFlag" >
<el-col style="display: flex">
<el-input v-model="login.validateCode" placeholder="請輸入驗證碼" style="width: 200px;"></el-input>
<img :src="validateImg" style="display: inline-block; border: solid 1px black; width: 100px; height: 34px; margin-left: 20px;
">
</el-col>
</el-row>
<div class="forget-choose">
<el-checkbox class="remember-me" v-model="login.rememberMe">記住我</el-checkbox>
<!--<div class="forget-password" @click="passwordVisible = true">忘記密碼?</div>-->
</div>
<el-row>
<el-col>
<el-button type="primary" @click="onSubmit">登錄</el-button>
</el-col>
</el-row>
</div>
</el-form>
</div>
</div>
</template>
created() {
if (Cookies.get('rememberMe') === true || Cookies.get('rememberMe') === 'true') {
this.login.rememberMe = true;
}
if(this.login.rememberMe){
this.login.password = Cookies.get('password');
this.login.email = Cookies.get('userEmail');
}else{
this.login.email = '';
this.login.password = '';
}
},
mounted(){
const self = this;
document.onkeypress = function (event) {
if(self.passwordVisible == false){
if(event.keyCode == 13 && self.$route.path === '/login'){
self.onSubmit();
}
}
}
},
watch: {
'login.rememberMe'(val){
this.$store.commit(types.REMEBER_ME_ACCOUNT, {data: val});
}
},
methods: {
onSubmit() {
if(!this.login.email || !this.login.password){
this.$message.info("請輸入賬號或密碼");
return;
}
if(this.isValidateCodePicFlag && !this.login.validateCode){
this.$message.info("請輸入驗證碼");
return;
}
if(this.isValidateCodePicFlag && this.login.validateCode.length !== 6){
this.$message.info("驗證碼輸入不正確");
return;
}
const loginData = `username=${this.login.email}&password=${this.login.password}&client_id=planner_jim&client_secret=7890ab&grant_type=password&scopes=bio notes`;
let params = {
UserName: this.login.email,
Password: this.login.password,
VerificationCode: this.login.validateCode,
VerificationCodeId: this.login.validateImgId,
}
Request.validatelogin(params, (data) => {
if(data.er === -1) {
Cookies.set('access_token', data.items.access_token);
Cookies.set('refresh_token', data.items.refresh_token);
Cookies.remove('loginemail');
Cookies.remove('userEmail');
Cookies.remove('password');
Cookies.remove('rememberMe');
Cookies.set('loginemail',this.login.email, {expires:7,path:'/'});
Cookies.set('userEmail',this.login.email, {expires:7,path:'/'});
Cookies.set('password',this.login.password, {expires:7,path:'/'});
if(this.login.rememberMe){
Cookies.set('rememberMe',true, {expires:7,path:'/'});
} else {
Cookies.set('rememberMe',false, {expires:7,path:'/'});
}
this.$store.commit(types.USER_TOKEN, {data: data});
this.$store.commit(types.GET_PROJECT_PROPOSAL_BY_ORG_ID, {data: []});
this.$router.push({path: '/chooseProject'});
}else if(data.er === -25) {
this.$message.info('賬號密碼錯誤!');
if(this.isValidateCodePicFlag) {
this.getImgValidateCode();
}
}else if(data.er === -26) {
Cookies.remove('loginemail');
Cookies.set('loginemail',this.login.email, {expires:7,path:'/'});
this.$router.push({path: '/chooseProject',query: {reset: true}})
}else if(data.er === 429) {
this.$message.info('賬號密碼錯誤!');
this.isValidateCodePicFlag = true;
this.getImgValidateCode();
}else if(data.er === -21) {
this.isValidateCodePicFlag = true;
this.$message.info('驗證碼錯誤!');
this.getImgValidateCode()
}
}, (err) => {
});
},