解决vue刷新页面以后丢失store的数据问题
刷新页面时vue实例重新加载,store就会被重置,可以把定义刷新前把store存入本地localStorage、sessionStorage、cookie中,localStorage是永久储存,重新打开页面时会读取上一次打开的页面数据,sessionStorage是储存到关闭为止,cookie不适合存大量数据。根据我的需求,最合适的是sessionStorage。
beforeunload在页面刷新时触发,可以监听这个方法,让页面在刷新前存store到sessionStorage中。
当然,在页面刷新时还要读取sessionStorage中的数据到store中,读取和储存都写在app.vue中。
exportdefault{
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
cnpminstallvuex--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本地存储的方法模块化
varstorage={
set(key,value){
localStorage.setItem(key,JSON.stringify(value));
//localStorage.key=value;
//localStorage[key]=value;
},
get(key){
returnJSON.parse(localStorage.getItem(key));
},
getForIndex(index){
returnlocalStorage.key(index);
},
getKeys(){
letitems=this.getAll();
letkeys=[];
for(letindex=0;index
3、创建store
importVuefrom'vue'
importVuexfrom'vuex'
importstoragefrom'@/model/storage'
Vue.use(Vuex);
//用Vuex.Store对象用来记录token
conststore=newVuex.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;
}
}
});
exportdefaultstore;
4、创建request
importaxiosfrom'axios'
importstorefrom'@/store'
importrouterfrom'@/router'
//createanaxiosinstance
constservice=axios.create({
//index.js设置了代理(解决跨域)invoice=http://58.246.79.142:25005
baseURL:"/invoice",//url=baseurl+requesturl
timeout:5000,//requesttimeout
}
})
//添加请求拦截器,若token存在则在请求头中加token,不存在也继续请求
service.interceptors.request.use(
config=>{
//每次发送请求之前检测都vuex存有token,那么都要放在请求头发送给服务器,没有则不带token
//Authorization是必须的
if(store.state.token){
config.headers.Authorization=store.state.token;
}
returnconfig;
},
error=>{
console.log("在request拦截器显示错误:",error.response)
returnPromise.reject(error);
}
);
//respone拦截器
service.interceptors.response.use(
response=>{
//在status正确的情况下,code不正确则返回对应的错误信息(后台自定义为200是正确,并且将错误信息写在message),正确则返回响应
returnresponse.data.code==200?response:Promise.reject(response.data.message);
},
error=>{
//在status不正确的情况下,判别status状态码给出对应响应
if(error.response){
console.log("在respone拦截器显示错误:",error.response)
switch(error.response.status){
case401:
//可能是token过期,清除它
//this.$store.commit("del_token");
store.commit("del_token");
router.replace({//跳转到登录页面
path:'/login',
//将跳转的路由path作为参数,登录成功后跳转到该路由
query:{redirect:router.currentRoute.fullPath}
});
}
}
returnPromise.reject(error.response.data);
}
);
exportdefaultservice
三、配置代理,封装路由router、设置路由守卫,在main.js中引入router
一、配置代理
二、封装路由router,并设置路由守卫
/*eslint-disable*/
importVuefrom'vue'
importRouterfrom'vue-router'
importMainfrom'@/main/index'
importstorefrom'@/store'
importstoragefrom'@/model/storage'
Vue.use(Router)
constroutes=[
{
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
}
]
constrouter=newRouter({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)orto.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,那么随它去吧
}
});
exportdefaultrouter
三、在main.js中引入router
importVuefrom'vue'
//importVuexfrom'vuex'
importAppfrom'./App'
importrouterfrom'./router'
importElementUIfrom'element-ui';
import'element-ui/lib/theme-chalk/index.css'
//importVueResourcefrom'vue-resource'
//importaxiosfrom'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;
newVue({
el:'#app',
router:router,
components:{App},
template:'
四、登录页面实际使用
只给出表单提交示例函数和依赖js
import{postLogin}from"@/api/login";
submitForm(formName){
this.$refs[formName].validate(valid=>{
if(valid){
letthat=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('formaterror:'+error);
console.log('formaterror:',error);
returnfalse;
}
});
}
上面依赖的@/api/login:
importrequestfrom'@/utils/request.js'
exportfunctionpostLogin(account,password){
console.log(account,password)
returnrequest({
url:'/login',
method:'post',
params:{
//具体传参(键)要看后台要求
account:account,
password:password
}
})
}
以上这篇解决vue刷新页面以后丢失store的数据问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
 