1. 程式人生 > 程式設計 >解決vue重新整理頁面以後丟失store的資料問題

解決vue重新整理頁面以後丟失store的資料問題

重新整理頁面時vue例項重新載入,store就會被重置,可以把定義重新整理前把store存入本地localStorage、sessionStorage、cookie中,localStorage是永久儲存,重新開啟頁面時會讀取上一次開啟的頁面資料,sessionStorage是儲存到關閉為止,cookie不適合存大量資料。根據我的需求,最合適的是sessionStorage。

beforeunload在頁面重新整理時觸發,可以監聽這個方法,讓頁面在重新整理前存store到sessionStorage中。

當然,在頁面重新整理時還要讀取sessionStorage中的資料到store中,讀取和儲存都寫在app.vue中。

export default {
 name: 'app',created () {
  // 在頁面載入時讀取sessionStorage
  if (sessionStorage.getItem('store')) {
   this.$store.replaceState(Object.assign({},this.$store.state,JSON.parse(sessionStorage.getItem('store'))))
  }
  // 在頁面重新整理時將store儲存到sessionStorage裡
  window.addEventListener('beforeunload',() => {
   sessionStorage.setItem('store',JSON.stringify(this.$store.state))
  })
 }
}

補充知識:vue專案將token存在(vuex)store和localstorage中

一、準備工作和token

1、準備工作

瞭解(session,cookie)token

Token的引入:Token是在客戶端頻繁向服務端請求資料,服務端頻繁的去資料庫查詢使用者名稱和密碼並進行對比,判斷使用者名稱和密碼正確與否,並作出相應提示,在這樣的背景下,Token便應運而生。

token 是在服務端產生的一串字串,以作客戶端進行請求的一個令牌。如果前端使用使用者名稱/密碼向服務端請求認證,服務端認證成功,那麼在服務端會返回 Token 給前端。前端可以在每次請求的時候帶上 Token 證明自己的合法地位。如果這個 Token 在服務端持久化(比如存入資料庫),那它就是一個永久的身份令牌(除非設定了有效期)。

token 優點

Token 完全由應用管理,所以它可以避開同源策略

Token 可以避免 CSRF 攻擊

Token 可以是無狀態的,可以在多個服務間共享

減輕伺服器的壓力,減少頻繁的查詢資料庫,使伺服器更加健壯。

安裝vuex

cnpm install vuex --save

2、介紹token用法

在前後端完全分離的情況下,Vue專案中實現token驗證大致思路如下:

1、第一次登入的時候,前端調後端的登陸介面,傳送使用者名稱和密碼

2、後端收到請求,驗證使用者名稱和密碼,驗證成功,就給前端返回一個token

3、前端拿到token,將token儲存到localStorage和vuex中,並跳轉路由頁面

4、前端每次跳轉路由,就判斷 localStroage 中有無 token ,沒有就跳轉到登入頁面,有則跳轉到對應路由頁面

5、每次調後端介面,都要在請求頭中加token

6、後端判斷請求頭中有無token,有token,就拿到token並驗證token,驗證成功就返回資料,驗證失敗(例如:token過期)就返回401,請求頭中沒有token也返回401

7、如果前端拿到狀態碼為401,就清除token資訊並跳轉到登入頁面

二、建立storage,store,request

1、src目錄:

解決vue重新整理頁面以後丟失store的資料問題

注:建立storage是可選的,因為我把localstorage(快取)封裝到了storage.js(本文後續程式碼均是用自己封裝的js);建立store是必須的!

2、建立storage(可選)

// 封裝操作localstorage本地儲存的方法 模組化

var storage = {
  set(key,value) {
    localStorage.setItem(key,JSON.stringify(value));
    // localStorage.key = value;
    // localStorage[key] = value;
  },get(key) {
    return JSON.parse(localStorage.getItem(key));
  },getForIndex(index) {
    return localStorage.key(index);
  },getKeys(){
    let items = this.getAll();
    let keys = [];
    for (let index=0;index<items.length;index++){
      keys.push(items[index].key);
    }
    return keys;
  },getLength() {
    return localStorage.length;
  },getSupport() {
    return (typeof (Storage) !== "undefined") ? true : false;
  },remove(key) {
    localStorage.removeItem(key);
  },removeAll() {
    localStorage.clear();
  },getAll() {
    let len = localStorage.length; // 獲取長度
    let arr = new Array(); // 定義資料集
    for (var i = 0; i < len; i++) {
      // 獲取key 索引從0開始
      var getKey = localStorage.key(i);
      // 獲取key對應的值
      var getVal = localStorage.getItem(getKey);
      // 放進陣列
      arr[i] = {
        'key': getKey,'val': getVal,}
    }
    return arr;
  }
}

export default storage;

3、建立store

import Vue from 'vue'
import Vuex from 'vuex'
import storage from '@/model/storage'

Vue.use(Vuex);
// 用Vuex.Store物件用來記錄token
const store = new Vuex.Store({

 state: {
  // 儲存token
  // token: storage.get('token') ? storage.get('token') : '',token:"",userName:"" // 可選
 },actions: {
  // removeToken: () => {
   // context.commit('set_token')
  // }
 },// 計算屬性
 mutations: {
  // 修改token,並將token存入localStorage
  set_token(state,token) {
   state.token = token;
   storage.set('token',token);
   console.log('store、localstorage儲存token成功!');
  },del_token(state) {
   state.token = "";
   storage.remove("token");
  },// 可選
  setUserInfo(state,userName) {
   state.userName = userName;
  }
 }
});

export default store;

4、建立request

import axios from 'axios'
import store from '@/store'
import router from '@/router'

// create an axios instance
const service = axios.create({
  // index.js設定了代理(解決跨域) invoice = http://58.246.79.142:25005
  baseURL: "/invoice",// url = base url + request url
  timeout: 5000,// request timeout
  }

})

//新增請求攔截器,若token存在則在請求頭中加token,不存在也繼續請求
service.interceptors.request.use(
  config => {
    // 每次傳送請求之前檢測都vuex存有token,那麼都要放在請求頭髮送給伺服器,沒有則不帶token
    // Authorization是必須的
    if (store.state.token) {
      config.headers.Authorization = store.state.token;
    }
    return config;
  },error => {
    console.log("在request攔截器顯示錯誤:",error.response)
    return Promise.reject(error);
  }
);

//respone攔截器
service.interceptors.response.use(
  response => {
    // 在status正確的情況下,code不正確則返回對應的錯誤資訊(後臺自定義為200是正確,並且將錯誤資訊寫在message),正確則返回響應
    return response.data.code == 200 ? response : Promise.reject(response.data.message);
  },error => { 
    // 在status不正確的情況下,判別status狀態碼給出對應響應
    if (error.response) {
      console.log("在respone攔截器顯示錯誤:",error.response)
      switch (error.response.status) {
        case 401:
          //可能是token過期,清除它
          // this.$store.commit("del_token"); 
          store.commit("del_token");

          router.replace({ //跳轉到登入頁面
            path: '/login',// 將跳轉的路由path作為引數,登入成功後跳轉到該路由
            query: { redirect: router.currentRoute.fullPath }
          });
      }
    }
    return Promise.reject(error.response.data);
  }
);


export default service

三、配置代理,封裝路由router、設定路由守衛,在main.js中引入router

一、配置代理

解決vue重新整理頁面以後丟失store的資料問題

二、封裝路由router,並設定路由守衛

/* eslint-disable */
import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/main/index'

import store from '@/store'
import storage from '@/model/storage'

Vue.use(Router)

const routes = [
 {
  path: '/',name: 'Main',redirect: '/login',// 某些頁面規定必須登入後才能檢視 ,可以在router中配置meta,將需要登入的requireAuth設為true,
  meta: {
   requireAuth: true,}
 },{
  path: '/login',component: () => import('@/views/login'),},{
  path: '/invoice',redirect: '/invoice',component: Main,]
 },{
  path: '*',component: Main
 }
]

const router = new Router({ routes: routes })

// 設定路由守衛,在進頁面之前,判斷有token,才進入頁面,否則返回登入頁面
if (storage.get("token")) {
 store.commit("set_token",storage.get("token"));
}
router.beforeEach((to,from,next) => {
 // 判斷要去的路由有沒有requiresAuth
 // to.matched.some(r => r.meta.requireAuth) or to.meta.requiresAuth
 if (to.matched.some(r => r.meta.requireAuth)) {
  if (store.state.token) {
   next(); //有token,進行request請求,後臺還會驗證token
  } else {
   next({
    path: "/login",// 將剛剛要去的路由path(卻無許可權)作為引數,方便登入成功後直接跳轉到該路由,這要進一步在登陸頁面判斷
    query: { redirect: to.fullPath } 
   });
  }
 } else {
  next(); //如果無需token,那麼隨它去吧
 }
});

export default router

三、在main.js中引入router

import Vue from 'vue'
// import Vuex from 'vuex'
import App from './App'
import router from './router'

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
// import VueResource from 'vue-resource'
// import axios from 'axios'

// 相容ie
// import 'babel-polyfill';

Vue.use(ElementUI);
// Vue.use(Vuex);
// Vue.use(VueResource);
// Vue.use(axios);

Vue.config.productionTip = false
Vue.component(CollapseTransition.name,CollapseTransition)
// this.$ajax 全域性使用axios
// Vue.prototype.$ajax=axios;

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

四、登入頁面實際使用

只給出表單提交示例函式和依賴js

import { postLogin } from "@/api/login";

submitForm(formName) {
   this.$refs[formName].validate(valid => {
    if (valid) {
     let that = this;
     // console.log('username',this.loginForm.username)
     // 通過校驗規則後進入校驗使用者名稱密碼是否正確
     postLogin(this.loginForm.username,this.loginForm.password)
      .then(res => {
       console.log(res);
       
        that.$store.commit("set_token",res.data.token);
        that.$store.commit("setUserInfo",res.data.account);

       this.$notify({
        title: "登入成功",type: "success",showClose: false,duration: 1000
       });
       setTimeout(() => {
        // 此時要判斷/login後面的引數,若無引數,進入主頁;
        this.$router.push("/index");
        // 若有引數則引數為未有許可權的那個路由,跳轉到那個路由
        // this.$router.push(***); -- 具體要自己在這實現
       },1000);
      })
      .catch(error => {
      // 錯誤分為 status-請求錯誤 和 code-賬號密碼錯誤
       this.$message.error(error);
       console.log(error);
      });
    } else {
    // 不符合前端校驗
     this.$message.error('format error:'+error);
     console.log('format error:',error);
     return false;
    }
   });
  }

上面依賴的@/api/login:

import request from '@/utils/request.js'

export function postLogin(account,password) {
  console.log(account,password)
  return request({
    url: '/login',method: 'post',params:{
    // 具體傳參(鍵)要看後臺要求
      account:account,password:password
    }
  })
}

以上這篇解決vue重新整理頁面以後丟失store的資料問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。