页面切换

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

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

data(){
    return{
      login:false
    }
  }
<Author v-if="!login"></Author>
       <div v-else>
         学生或者老师的页面
       </div>

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

通过promise

//拦截器 回复
api.interceptors.response.use(response=>{
 return response.data.data;
},error=>{
 const response=error.response;
 Vue.$notification.error({
     message:"API Error",
     description:response.data.errorMessage
 });
//加上这句
 return Promise.reject(error);
})

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

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

子组件:

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

父组件:

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

4.通过Vuex来传值

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

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

const state = {
    

}
const getters = {

}

const mutations = {

}

const actions = {

}

export default {
    state,
    getters,
    mutations,
    actions
}

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

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

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)

export default new Vuex.Store({
    state: { //状态
    },
    mutations: {},
    actions: {},
    modules: {
        user
    }
})

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

在user.js中

export default {
    namespaced: true,
    state,
    getters,
    mutations,
    actions
}

4.4.在user.js中定义login

const state = {
    login: false
}

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

 computed:{
    login(){
      return this.$store.state.user.login
    }
  }

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

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

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

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

const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(form);
    }
}

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

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

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

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

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

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

import { api } from "../../utils/api";
const mutations = {
    loginon(state) {
        state.login = true;
    }
}

const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(commit);
        api.post("/auth/login", form).then(result => {
            console.log(result);
            commit("loginon");
        });
    }
}

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

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

import { api } from "../../utils/api"
const state = {
    login: false,
    //存信息
    info:{

    }
}
const getters = {

}

const mutations = {
    loginon(state,data) {
        state.login = true;
        state.info=data;
    }
}

const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(commit);
        api.post("/auth/login", form).then(result => {
            console.log(result);
            commit("loginon",result);
        });
    }
}

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

  computed:{
    login(){
      return this.$store.state.user.login
    },
    info(){
       return this.$store.state.user.info
    }
  }

然后再渲染出来

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

 computed:{
    isTeacher(){
      return this.info.is_admin>0
    }
  },
  components: {
    Author

  }

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

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

<div v-else>
         <Teacher v-if="isTeacher"></Teacher>
         <Student v-else></Student>
       </div>

4.8.辅助函数的使用

<script>
import {mapState} from "vuex"

export default {
  computed:{
     //获取user下面的info,不然会默认找到store下面
    ...mapState("user",["info","login"]),
    // login(){
    //   return this.$store.state.user.login
    // },
    // info(){
    //    return this.$store.state.user.info
    // },
   
  }
  
}
</script>

自动登录

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

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

在user.js中

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

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

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

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

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

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

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

可以使用插件

1.下载

npm install vuex-persistedstate --save

plugins是vuex的插件

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

2.使用

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

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
 
export default new Vuex.Store({
   
    modules: {
        user
    },
    plugins:[
      createPersistedState({
        
      })
    ]
})

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

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)

export default new Vuex.Store({

    modules: {
        user
    },
    plugins: [
        createPersistedState({
            key: "eStudy",
            paths: ["user"]
        })
    ]
})

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

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

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

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)

export default new Vuex.Store({

    modules: {
        user
    },
    plugins: [
        createPersistedState({
            key: "eStudy",
            paths: ["user"],
            subscriber(store) {
                return function(handler) {
                    return store.subscribe(handler);
                }
            }
        })
    ]
})

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

看一下接口的请求参数:

在user.js中

const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(commit);
        api.post("/auth/login", form).then(result => {
            console.log(result);
            commit("loginon", result);
        });
    },
    //验证token
    //commit提交mutation来改变当前的状态
    checkedLogin({ commit, state }) {
        //怎么传递请求头呢
        api.defaults.headers.common["Token"] = state.info.token;
        api.post("/auth/refreshToken").then((token) => {
            console.log(token);

        }).catch(err => {
            console.log(err);
        })
        console.log(commit);

    }
}

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

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)

export default new Vuex.Store({

    modules: {
        user
    },
    plugins: [
        createPersistedState({
            key: "eStudy",
            paths: ["user"],
            subscriber(store) {
                store.dispatch("user/checkedLogin");
                return function(handler) {
                    return store.subscribe(handler);
                }
            }
        })
    ]
})

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

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

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

在user.js中

先赋值,再调用

const mutations = {
    loginon(state, data) {
        state.login = true;
        state.info = data;
    },
    updateToken(state,token){
        //赋值
        state.info.token=token;
    }
}
const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(commit);
        api.post("/auth/login", form).then(result => {
            console.log(result);
            commit("loginon", result);
        });
    },
    //验证token
    //commit提交mutation来改变当前的状态
    checkedLogin({ commit, state }) {
        console.log(commit);
        //怎么传递请求头呢
        api.defaults.headers.common["Token"] = state.info.token;
        api.post("/auth/refreshToken").then((token) => {
            console.log(token);
            //调用
            commit("updateToken",token);

        }).catch(err => {
            console.log(err);
        })

    }
}

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

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

const actions = {

    logout({ commit }) {
        commit("logout");
    }
}

2.login为false返回登录界面

const mutations = {
   
    logout(state) {
        state.info = {};
        state.login = false;
    }
}

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

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

const actions = {
    //context为环境对象
    login({ commit }, form) {
        console.log(commit);
        api.post("/auth/login", form).then(result => {
            console.log(result);
            commit("loginon", result);
        });
    },
    //验证token
    //commit提交mutation来改变当前的状态
    checkedLogin({ commit, state, dispatch }) {
        console.log(commit);
        //怎么传递请求头呢
        api.defaults.headers.common["Token"] = state.info.token;
        api.post("/auth/refreshToken").then((token) => {
            console.log(token);
            commit("updateToken", token);

        }).catch(err => {
            console.log(err);
            dispatch("logout");
        })

    },
    logout({ commit }) {
        commit("logout");
    }
}

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

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

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

 checkedLogin({ commit, state, dispatch }) {
        console.log(commit);
        //怎么传递请求头呢
        api.defaults.headers.common["Token"] = state.info.token;
        api.post("/auth/refreshToken", {}, { _slient: true }).then((token) => {
            console.log(token);
            commit("updateToken", token);

        }).catch(err => {
            console.log(err);
            dispatch("logout");
        })

    }

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

console.dir(error);

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

//拦截器
api.interceptors.response.use(response => {
    return response.data.data;
}, error => {
    console.dir(error);
    const config = error.config;
    const response = error.response;
    if (!config._slient) {
        Vue.$notification.error({
            message: "API Error",
            description: response.data.errorMessage
        });
    }

    return Promise.reject(error);
})

 

Logo

前往低代码交流专区

更多推荐