登录跳转
上节中我们把JWT存放到了localStorage中,但是用户遇到一些突然断网,或者JWT过期的问题,这时需要弹出一个窗口询问是否重新登录。用户点击重新登录,跳转到signin页面,登录成功后再跳回用户刚刚访问的界面。我们把这个跳回的操作命名为return_to。
由于这是一个跨页面的操作,所以我们把这个return_to可以放到全局的状态管理,或者localStorage中
思路1:用户点击登录时,会触发localStorage.setItem(return_to,path)点击时就会存下这两个参数。登录成功后,再去getItem就可以了。 思路2:查询参数——queryString 比如点击登录跳转到signin界面时传一个'/sign_in?return_to',登录成功后只需要读取return_to这样一个参数,然后跳转回去即可
这两个思路可以实现,页面(路由)切换时保持不变。
思路1实现
之前我们使用的history有一个问题就是只会改变地址栏,所以要实现跳转还是要用vue-router。
存放之后进行读取,再判断。
思路2实现
我们要使用useRoute。
useRoute和useRouter的区别:
useRouter是路由器,可以通过router.push()来改变路由,useRoute是路由信息,里面只有信息没有push
跳过广告(路由守卫)
我们这个项目打开默认是从第一页广告开始,如果用户已经点完了,退出了网页。第二天再次打开,还是会从头开始。所以我们需要一个标记,来优化体验。
思路:当用户点击跳过或者点击完成时就在本地记录一下localStorage。由于开场的四个界面都有跳过,我们考虑重新封装一个跳过的按钮以供复用。
核心需求就是点击跳过实现跳转的同时能打上一个标记。注意localStorage只能存储字符串。
回到开始的四个页面分别使用SkipFeatures组件。
不仅仅是跳过,完成时也要做同样的事情
这时回到路由,我们需要在定义路由的时候直接做检查,可以使用beforeEnter
如果发现localStorage中的skipFeature是yes,那么就直接跳转到开始界面,否则按原来的继续进行
登录检查
只有登陆了才能进行记账。如果没有登录就会提示要求登录。在进入记一笔也就是items界面前面添加路由守卫,首先发一个请求获取当前用户的信息,如果成功就直接next,没有成功就重新定向到登录界面。
在封装好的HTTP组件里,要加一个请求的拦截器。接受两个参数。他会给我们传来一个config包含所有请求相关的配置,我们只需要在config的header里面添加jwt
config.headers!.Authorization = `Bearer ${jwt}`
每个页面都要做登录检查
我们从使用逻辑来看,不只是item页面要做登录检查,其实包括统计页面在内的很多页面都需要做登录检查。在每个路由下面做路由守卫过于复杂,所以我们采取别的方式。 思路:可以在全局路由的守卫里面做一个白名单,也就是说除了根路径,signin,和welcome这几个页面是不需要检查的。需要检查的路由更多,所以我们可以反向思考
去vue-router官网找到全局守卫相关的部分。
我们进入main.ts,在路由器router的后面加上全局守卫。
这样就保证了每个页面都会自动检查登录。但是这样每进入一个新的页面,都会进行登录检查的请求。我需要的进行了一次登录检查,以后就不会进行了。所以要进行优化。
思路:在进入路由器的时候就直接进行请求,后面都会使用第一次请求的结果。以后就不会多次请求了
我们删除jwt进行测试,发现跳过了登录界面,还是会跳转到当前了浏览界面。问题在于:不能在false的结果里面return,需要将其return到外部
我们用一个promise来发送这个/me的请求,如果可以获取用户信息则返回true,否则跳转登录。
此时依然有一个bug,这时登录成功返回刚才的界面,/me的请求依然是失败的,因为这个请求一早就发送了且只发送一次,这个失败的结果是不会改变的。 思路:我们要主动去更新/me的这个请求,所以封装一个借口来进行对这个promise的更新。 新建me.tsx,要暴露两个东西,一个是promise,一个是refreshMe
导出一个刷新用户信息的借口和refreshMe一样 只是为了区别命名
export const fetchMe = refreshMe
并且在signinPage也进行刷新
这时我们的登录检查到此完成