Vue+Vuex 實現自動登錄功能


剛剛實現了Vue+Vuex的自動登錄功能,在實現的時候遇到了一些問題,這里記錄一下:

因為這個還不夠完善,在寫完下列代碼后,又進行了補充,可以從https://www.cnblogs.com/xiaoxineryi/p/12405563.html 看到補充內容

一、對於vuex的簡單理解:

可以參考這個:https://zhuanlan.zhihu.com/p/24357762https://segmentfault.com/a/1190000009404727

還有官網文檔:https://vuex.vuejs.org/zh/guide/getters.html

差不多理解就是,vuex里面,用state來存儲數據,在mutations里面寫保存數據的函數,並且提供給外部調用,在getters中寫獲取數據的函數,在actions里面寫獲取數據后、寫入數據前的處理過程。

二、在看網上很多示例的時候,代碼寫得挺好的,但是沒有總的項目目錄,一個函數一個函數的寫,卻又不知道要放在哪里,就感覺很別扭,所以我先把項目目錄列出來:因為只用到了src下的,其他的按新建項目的就好

            

①:上一章的前后端分離里面,數據傳遞確實做到了,但是在Login.vue里面寫的,很多重復的內容完全可以重用,所以這次干脆提出一個api來,專門用來傳遞數據。

  另外,此次使用的是aoxis,本身就已經封裝好很多了。

import axios from 'axios'

let base = 'http://127.0.0.1:8090';
export const postRequest = (url, params) => {
  return axios({
    method: 'post',
    url: `${base}${url}`,
    data: params,
    transformRequest: [function (data) {
      // Do whatever you want to transform the data
      let ret = ''
      for (let it in data) {
        ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
      }
      return ret
    }],
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  });
}
api.js

  base的路徑,按照自己服務器的端口進行修改。

②:現在先在store里,定義好數據和方法(就相當於數據庫):store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({

  state: {
    // 存儲token
    Authorization: localStorage.getItem('Authorization') ? localStorage.getItem('Authorization') : ''
  },

  mutations: {
    // 修改token,並將token存入localStorage
    changeLogin (state, user) {
      // alert(user.Authorization);
      state.Authorization = user.Authorization;
      localStorage.setItem('Authorization', user.Authorization);
    }
  }
});

export default store;

 

  這里state里面就是存儲的數據,這里就是存儲用戶的token,下面mutations,寫了一個修改token的方法,這個方法將token寫入localStorage,而且保存到自己的state中。

③:定義好了數據和方法以后,自動登錄就是要在用戶訪問頁面的時候,自動檢查有沒有token,token對不對:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import VueResource from 'vue-resource'
import 'element-ui/lib/theme-chalk/index.css'
// import './styles/element-variables.scss'
import './styles/font-awesome-4.7.0/css/font-awesome.min.css'
import './utils/filter_utils.js'
import store from './store'
import axios from 'axios'

Vue.use(ElementUI)
// Vue.use(VueResource)
Vue.config.productionTip = false
// Vue.http.options.emulateJSON = true
/* eslint-disable no-new */


new Vue({
  el: '#app',
  router,
  store:store,
  components: { App },
  template: '<App/>'
})


axios.interceptors.request.use(
  config => {
    if (localStorage.getItem('Authorization')) {
      config.headers.Authorization = localStorage.getItem('Authorization');
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  });
main.js

 

  在這里面,有兩個需要注意的:

  第一個就是,因為定義了store,所以在常規的main之外,還在Vue里面多加了一個store,否則的話,在使用的使用就相當於與沒有注冊,查找不到,經常有如下錯誤:

  Cannot read property 'commit' of undefined 

  第二個就是下面的攔截器:因為只是對全局的訪問都配置,所以直接就在全局中寫了,而且前面是axios.interceptors.request.xx,前面的axios就表示了是全局的。

  如果要對某個方法來使用,應該先創建一個axios,然后假設這個變量名為xx,則使用xx.interceptors來執行,后面用request或者response來表示是請求數據還是響應數據。

  更詳細的可以看https://www.jianshu.com/p/646ed4edf51f

④:在router/index.js中,也就是路由里面,也需要添加內容:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import login from '@/components/login.vue'
import home from '@/components/home.vue'
import logo from '@/components/HelloWorld.vue'
Vue.use(Router);


const router = new Router({
  mode:'history',
  routes:[
  {
    path:'/login',
      name:'登錄',
    component:login,
  },
  {
    path:'/',
    name:'主頁',
    component:logo,
  }
]
});

router.beforeEach((to,from,next)=>{
  if(to.path ==='/login'){
    next();
  }else {
    let token = localStorage.getItem('Authorization');
    if(token ===null || token ===''){
      next('/login');
    }else {
      // alert(localStorage.getItem("Authorization"));
      next();
    }
  }
});

export default router;

  第一點就是將router加上mode:'history',這個也不知道為啥,反正我寫的時候,沒有這個就不管什么頁面都跳轉到首頁,怎么調都不管用,加上這一句話就好了。

  第二個就是定義了一個beforeEach的函數,這個可以檢測來的請求路徑、去的請求路徑,加上token檢測,可以讓用戶如果沒有登錄就自動跳轉到登錄界面。

⑤:再寫登錄頁面:

<template>
  <el-form :rules="rules" class="login-container" label-position="left"
           label-width="0px" v-loading="loading">
    <h3 class="login_title">系統登錄</h3>
    <el-form-item prop="account">
      <el-input type="text" v-model="loginForm.username" auto-complete="off" placeholder="賬號"></el-input>
    </el-form-item>
    <el-form-item prop="checkPass">
      <el-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="密碼"></el-input>
    </el-form-item>
    <el-checkbox class="login_remember" v-model="checked" label-position="left">記住密碼</el-checkbox>
    <el-form-item style="width: 100%">
      <el-button type="primary" @click.native.prevent="submitClick" style="width: 100%">登錄</el-button>
    </el-form-item>
  </el-form>
</template>
<script>
  import {postRequest} from '../utils/api'
  import {putRequest} from '../utils/api'
  import { mapMutations } from 'vuex';
  export default{
    data(){
      return {
        rules: {
          account: [{required: true, message: '請輸入用戶名', trigger: 'blur'}],
          checkPass: [{required: true, message: '請輸入密碼', trigger: 'blur'}]
        },
        checked: true,
        loginForm: {
          username: '11',
          password: '123'
        },
        loading: false
      }
    },
    methods: {
      ...mapMutations(['changeLogin']),
      submitClick: function () {
        var _this = this;
        this.loading = true;
        postRequest('/login', {
          username: this.loginForm.username,
          password: this.loginForm.password
        }).then(resp=> {
          _this.loading = false;
          if (resp.status == 200) {
            //成功
            var json = resp.data;
            if (json.status == 'success') {

              _this.userToken = 123;
              // localStorage.setItem('Authorization',_this.userToken);
              _this.changeLogin({Authorization:_this.userToken});
              _this.$router.replace({path: '/'});
            } else {
              _this.$alert('登錄失敗!', '失敗!');
            }
          } else {
            //失敗
            _this.$alert('登錄失敗!', '失敗!');
          }
        }, resp=> {
          _this.loading = false;
          _this.$alert('找不到服務器⊙﹏⊙∥!', '失敗!');
        });
      }
    }
  }
</script>
<style>
  .login-container {
    border-radius: 15px;
    background-clip: padding-box;
    margin: 180px auto;
    width: 350px;
    padding: 35px 35px 15px 35px;
    background: #fff;
    border: 1px solid #eaeaea;
    box-shadow: 0 0 25px #cac6c6;
  }

  .login_title {
    margin: 0px auto 40px auto;
    text-align: center;
    color: #505458;
  }

  .login_remember {
    margin: 0px 0px 35px 0px;
    text-align: left;
  }
</style>

 

這里一定不要忘了引入函數

⑥在這里我們可以看到,返回的是json數據,對應后台可以:先創建一個Bean,用來專門返回響應內容:

package com.example.Bean;


public class RespBean {
    private String status;
    private String msg;

    public RespBean() {
    }

    public RespBean(String status, String msg) {

        this.status = status;
        this.msg = msg;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

  而在controller中,直接調用即可:

package com.example.Controller;

import com.example.Bean.RespBean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @CrossOrigin(origins = "*")
    @RequestMapping("/login")
    public RespBean login(
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "password",required = false) String password,
            Model model
    ){
        System.out.println("用戶名為"+username);
        System.out.println("密碼為"+password);
        if (username.equals("11")){
            return new RespBean("success","登錄成功");
        }else{
            return new RespBean("fail","登錄失敗");
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM