解决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;index3、创建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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。