解决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 (Item('store')) {
this.$placeState(Object.assign({}, this.$store.state, JSON.Item('store'))))
}
// 在页⾯刷新时将store保存到sessionStorage⾥
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state))
})
}
}
补充知识:vue项⽬将token存在(vuex)store和localstorage中
⼀、准备⼯作和token
1、准备⼯作
了解(session,cookie)token
js获取json的key和valueToken的引⼊: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⽬录:
注:创建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.Item(key));
},
getForIndex(index) {
return localStorage.key(index);
},
getKeys(){
let items = All();
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) {
},
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 = Item(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: ('token') ? ('token') : '',
token:"",
userName:"" // 可选
},
actions: {
// removeToken: () => {
// contextmit('set_token')
// }
},
// 计算属性
mutations: {
// 修改token,并将token存⼊localStorage
set_token(state,token) {
storage.set('token', token);
console.log('store、localstorage保存token成功!');
},
del_token(state) {
},
// 可选
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 = ate({
// index.js设置了代理(解决跨域) invoice = 58.246.79.142:25005  baseURL: "/invoice", // url = base url + request url
timeout: 5000, // request timeout
}
})
//添加请求,若token存在则在请求头中加token,不存在也继续请求
quest.use(
config => {
// 每次发送请求之前检测都vuex存有token,那么都要放在请求头发送给服务器,没有则不带token
// Authorization是必须的
if (ken) {
config.headers.Authorization = ken;
}
return config;
},
error => {
console.log("在request显⽰错误:", sponse)
ject(error);
}
);
//respone
sponse.use(
response => {
// 在status正确的情况下,code不正确则返回对应的错误信息(后台⾃定义为200是正确,并且将错误信息写在message),正确则返回响应    return de == 200 ? response : ject(ssage);
},
error => {
// 在status不正确的情况下,判别status状态码给出对应响应
if (sponse) {
console.log("在respone显⽰错误:", sponse)
switch (sponse.status) {
case 401:
//可能是token过期,清除它
// this.$storemit("del_token");
storemit("del_token");
path: '/login',
/
/ 将跳转的路由path作为参数,登录成功后跳转到该路由
query: { redirect: router.currentRoute.fullPath }
});
}
}
sponse.data);
}
);
export default service
三、配置代理,封装路由router、设置路由守卫,在main.js中引⼊router
⼀、配置代理
⼆、封装路由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 (("token")) {
storemit("set_token", ("token"));
}
router.beforeEach((to, from, next) => {
// 判断要去的路由有没有requiresAuth
// to.matched.some(r => quireAuth) a.requiresAuth
if (to.matched.some(r => quireAuth)) {
if (ken) {
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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。