飞道的博客

vue实现不用路由的页面切换与自动登录

554人阅读  评论(0)

页面切换

我做的后台页面较少,所以不需要用到路由

1.登录后切换到老师或者学生的页面,通过is_admin来判断登录的是老师还是学生


  
  1. data(){
  2. return{
  3. login: false
  4. }
  5. }

  
  1. <Author v-if="!login"> </Author>
  2. <div v-else>
  3. 学生或者老师的页面
  4. </div>

2.问题:无论成功或者失败,都是走成功的回调函数,怎么解决呢?

通过promise


  
  1. //拦截器 回复
  2. api.interceptors.response.use( response=>{
  3. return response.data.data;
  4. },error=>{
  5. const response=error.response;
  6. Vue.$notification.error({
  7. message: "API Error",
  8. description:response.data.errorMessage
  9. });
  10. //加上这句
  11. return Promise.reject(error);
  12. })

报错,因为我并没有写失败的回调函数

3.子组件通过自定义事件往父组件传值

子组件:


  
  1. submit(){
  2. //地址,参数
  3. api.post( "/auth/login", this.form).then( data=>{
  4. console.log(data);
  5. this.$emit( "changeLog");
  6. });
  7. }

父组件:

  <Author v-if="!login" @changeLog="login=true"></Author>

4.通过Vuex来传值

4.1.在store下面新建modules文件夹,然后新建文件user.js

声明四个变量,然后暴露出去


  
  1. const state = {
  2. }
  3. const getters = {
  4. }
  5. const mutations = {
  6. }
  7. const actions = {
  8. }
  9. export default {
  10. state,
  11. getters,
  12. mutations,
  13. actions
  14. }

4.2.在store.js中怎么使用user.js文件呢?

两步,一:引入,二:在模块中定义


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import user from './modules/user'
  4. Vue.use(Vuex)
  5. export default new Vuex.Store({
  6. state: { //状态
  7. },
  8. mutations: {},
  9. actions: {},
  10. modules: {
  11. user
  12. }
  13. })

4.3.为了避免模块在融合的时候,起了冲突,要加上命名空间:namespaced的概念

在user.js中


  
  1. export default {
  2. namespaced: true,
  3. state,
  4. getters,
  5. mutations,
  6. actions
  7. }

4.4.在user.js中定义login


  
  1. const state = {
  2. login: false
  3. }

在App.vue中通过计算属性监听login可以使用到这个定义的login


  
  1. computed:{
  2. login(){
  3. return this.$store.state.user.login
  4. }
  5. }

4.5.怎么把数据进行改变呢?

点击提交向后台发送请求,但是请求是异步的,通过dispatch去触发action


  
  1. submit(){
  2. //地址,参数
  3. api.post( "/auth/login", this.form).then( data=>{
  4. console.log(data);
  5. this.$store.dispatch( 'login', this.form);
  6. });
  7. }

在user.js中看有没有触发,打印一下


  
  1. const actions = {
  2. //context为环境对象
  3. login({ commit }, form) {
  4. console.log(form);
  5. }
  6. }

报错,是因为命名空间的关系,都隔了一层,要加上user,要加什么看你怎么命名


  
  1. submit(){
  2. //地址,参数
  3. api.post( "/auth/login", this.form).then( data=>{
  4. console.log(data);
  5. this.$store.dispatch( 'user/login', this.form);
  6. });
  7. }

这样就可以把form传到user.js中

遇到一个问题:我定义却没有使用,ESLint会报我错误,目前的解决办法只有在安装的时候不安装ESLint

4.6.怎么把login的false变成true,在user.js中

当我们提交用户和密码时,要触发一个actions,发送ajax请求,请求成功的话,要把login的状态变成true


  
  1. import { api } from "../../utils/api";
  2. const mutations = {
  3. loginon(state) {
  4. state.login = true;
  5. }
  6. }
  7. const actions = {
  8. //context为环境对象
  9. login({ commit }, form) {
  10. console.log(commit);
  11. api.post( "/auth/login", form).then( result => {
  12. console.log(result);
  13. commit( "loginon");
  14. });
  15. }
  16. }

4.7.怎么切换成老师或者学生的界面

在user.js中先是在state里面定义info,接着在actions来commit这result,最后在mutations里面去赋值。


  
  1. import { api } from "../../utils/api"
  2. const state = {
  3. login: false,
  4. //存信息
  5. info:{
  6. }
  7. }
  8. const getters = {
  9. }
  10. const mutations = {
  11. loginon(state,data) {
  12. state.login = true;
  13. state.info=data;
  14. }
  15. }
  16. const actions = {
  17. //context为环境对象
  18. login({ commit }, form) {
  19. console.log(commit);
  20. api.post( "/auth/login", form).then( result => {
  21. console.log(result);
  22. commit( "loginon",result);
  23. });
  24. }
  25. }

要在App.vue中去使用这个登录信息,要先拿到info


  
  1. computed:{
  2. login(){
  3. return this.$store.state.user.login
  4. },
  5. info(){
  6. return this.$store.state.user.info
  7. }
  8. }

然后再渲染出来

学生的is_admin为0,老师的is_admin为1


  
  1. computed:{
  2. isTeacher(){
  3. return this.info.is_admin> 0
  4. }
  5. },
  6. components: {
  7. Author
  8. }

isTeacher为true的时候,切换到老师页面,

isTeacher为false的时候,切换到学生页面。


  
  1. <div v-else>
  2. <Teacher v-if="isTeacher"> </Teacher>
  3. <Student v-else> </Student>
  4. </div>

4.8.辅助函数的使用


  
  1. <script>
  2. import {mapState} from "vuex"
  3. export default {
  4. computed:{
  5. //获取user下面的info,不然会默认找到store下面
  6. ...mapState( "user",[ "info", "login"]),
  7. // login(){
  8. // return this.$store.state.user.login
  9. // },
  10. // info(){
  11. // return this.$store.state.user.info
  12. // },
  13. }
  14. }
  15. </script>

自动登录

点击登录的时候把状态存到localStorage

键值的形式,我们要传对象,会存两个值,它会把他转成字符串,所以要用JSON.stringify

在user.js中


  
  1. const mutations = {
  2. loginon(state, data) {
  3. state.login = true;
  4. state.info = data;
  5. //键值的形式,我们要传对象,会存两个值,它会把他转成字符串,所以要用JSON.stringify
  6. localStorage.setItem( "eStudy", JSON.stringify({ login: true, info: JSON.stringify(data) }))
  7. }
  8. }

使用前要清空一下数据,然后点击登录,测试有没有存成功

在这底下可以看到存的login和info

在user.js中怎么从localStorage中取值呢?

要先解析字符串,也有可能取不到值


  
  1. const eStudy = JSON.stringify(localStorage.getItem( "eStudy")) || {};
  2. const state = {
  3. login: eStudy.login || false,
  4. info: eStudy.info ? JSON.parse(eStudy.info) : {}
  5. }

我们自己去存localStorage,并且自己去取,其实是挺麻烦的

可以使用插件

1.下载

npm install vuex-persistedstate --save

plugins是vuex的插件

如果我们去提交mutations,那它会把mutations里面的值全部存到localStorage

2.使用

在store的index.js中,要先引入,然后在plugins里面配置


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import user from './modules/user'
  4. import createPersistedState from 'vuex-persistedstate'
  5. Vue.use(Vuex)
  6. export default new Vuex.Store({
  7. modules: {
  8. user
  9. },
  10. plugins:[
  11. createPersistedState({
  12. })
  13. ]
  14. })

并不是所有的数据都要存在localStorage,写模块化就可以避免这种情况,我们只把登录的相关信息存到user里面


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import user from './modules/user'
  4. import createPersistedState from 'vuex-persistedstate'
  5. Vue.use(Vuex)
  6. export default new Vuex.Store({
  7. modules: {
  8. user
  9. },
  10. plugins: [
  11. createPersistedState({
  12. key: "eStudy",
  13. paths: [ "user"]
  14. })
  15. ]
  16. })

自动登录到这边就做完了,

但是自动登录是要有时间限制的,通过验证token过没过期,来决定是否可以登录

订阅函数:当前的mutation和localStorage之间的关系,subscriber,初始化的钩子函数


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import user from './modules/user'
  4. import createPersistedState from 'vuex-persistedstate'
  5. Vue.use(Vuex)
  6. export default new Vuex.Store({
  7. modules: {
  8. user
  9. },
  10. plugins: [
  11. createPersistedState({
  12. key: "eStudy",
  13. paths: [ "user"],
  14. subscriber(store) {
  15. return function(handler) {
  16. return store.subscribe(handler);
  17. }
  18. }
  19. })
  20. ]
  21. })

我们的token的接口是7天,7天没登就过期了,在第六天登录了,还能在续期7天。

看一下接口的请求参数:

在user.js中


  
  1. const actions = {
  2. //context为环境对象
  3. login({ commit }, form) {
  4. console.log(commit);
  5. api.post( "/auth/login", form).then( result => {
  6. console.log(result);
  7. commit( "loginon", result);
  8. });
  9. },
  10. //验证token
  11. //commit提交mutation来改变当前的状态
  12. checkedLogin({ commit, state }) {
  13. //怎么传递请求头呢
  14. api.defaults.headers.common[ "Token"] = state.info.token;
  15. api.post( "/auth/refreshToken").then( (token) => {
  16. console.log(token);
  17. }).catch( err => {
  18. console.log(err);
  19. })
  20. console.log(commit);
  21. }
  22. }

在store文件夹下的index.js中去触发checkedLogin函数,通过store.dispatch方法


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import user from './modules/user'
  4. import createPersistedState from 'vuex-persistedstate'
  5. Vue.use(Vuex)
  6. export default new Vuex.Store({
  7. modules: {
  8. user
  9. },
  10. plugins: [
  11. createPersistedState({
  12. key: "eStudy",
  13. paths: [ "user"],
  14. subscriber(store) {
  15. store.dispatch( "user/checkedLogin");
  16. return function(handler) {
  17. return store.subscribe(handler);
  18. }
  19. }
  20. })
  21. ]
  22. })

如果验证成功了,我们可以看到token信息

如果成功应该续费,要更新token

想直接改变状态,要通过mutations去改变

在user.js中

先赋值,再调用


  
  1. const mutations = {
  2. loginon(state, data) {
  3. state.login = true;
  4. state.info = data;
  5. },
  6. updateToken(state,token){
  7. //赋值
  8. state.info.token=token;
  9. }
  10. }

  
  1. const actions = {
  2. //context为环境对象
  3. login({ commit }, form) {
  4. console.log(commit);
  5. api.post( "/auth/login", form).then( result => {
  6. console.log(result);
  7. commit( "loginon", result);
  8. });
  9. },
  10. //验证token
  11. //commit提交mutation来改变当前的状态
  12. checkedLogin({ commit, state }) {
  13. console.log(commit);
  14. //怎么传递请求头呢
  15. api.defaults.headers.common[ "Token"] = state.info.token;
  16. api.post( "/auth/refreshToken").then( (token) => {
  17. console.log(token);
  18. //调用
  19. commit( "updateToken",token);
  20. }).catch( err => {
  21. console.log(err);
  22. })
  23. }
  24. }

Token没过期保持登录,Token过期了的话,返回登录界面

1.先在action里面写,然后通过commit触发mutation里面的logout函数


  
  1. const actions = {
  2. logout({ commit }) {
  3. commit( "logout");
  4. }
  5. }

2.login为false返回登录界面


  
  1. const mutations = {
  2. logout(state) {
  3. state.info = {};
  4. state.login = false;
  5. }
  6. }

3.这样还不行,需要在验证token的函数的token过期的回调函数中触发这个登出的函数,

通过传dispatch,并通过dispatch去触发登出的函数


  
  1. const actions = {
  2. //context为环境对象
  3. login({ commit }, form) {
  4. console.log(commit);
  5. api.post( "/auth/login", form).then( result => {
  6. console.log(result);
  7. commit( "loginon", result);
  8. });
  9. },
  10. //验证token
  11. //commit提交mutation来改变当前的状态
  12. checkedLogin({ commit, state, dispatch }) {
  13. console.log(commit);
  14. //怎么传递请求头呢
  15. api.defaults.headers.common[ "Token"] = state.info.token;
  16. api.post( "/auth/refreshToken").then( (token) => {
  17. console.log(token);
  18. commit( "updateToken", token);
  19. }).catch( err => {
  20. console.log(err);
  21. dispatch( "logout");
  22. })
  23. },
  24. logout({ commit }) {
  25. commit( "logout");
  26. }
  27. }

实现token过期,返回登录页面。

不想要请先登录这个提示信息

1.在登录的时候设置{ _slient: true }


  
  1. checkedLogin({ commit, state, dispatch }) {
  2. console.log(commit);
  3. //怎么传递请求头呢
  4. api.defaults.headers.common[ "Token"] = state.info.token;
  5. api.post( "/auth/refreshToken", {}, { _slient: true }).then( (token) => {
  6. console.log(token);
  7. commit( "updateToken", token);
  8. }).catch( err => {
  9. console.log(err);
  10. dispatch( "logout");
  11. })
  12. }

2.我们在api.js中通过dir,测试一下

console.dir(error);

3.在拦截器中设置想要提示用户哪些内容,哪些不提示用户


  
  1. //拦截器
  2. api.interceptors.response.use( response => {
  3. return response.data.data;
  4. }, error => {
  5. console.dir(error);
  6. const config = error.config;
  7. const response = error.response;
  8. if (!config._slient) {
  9. Vue.$notification.error({
  10. message: "API Error",
  11. description: response.data.errorMessage
  12. });
  13. }
  14. return Promise.reject(error);
  15. })

 


转载:https://blog.csdn.net/weixin_42995083/article/details/106433313
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场