vue实现不用路由的页面切换与自动登录
页面切换我做的后台页面较少,所以不需要用到路由1.登录后切换到老师或者学生的页面,通过is_admin来判断登录的是老师还是学生data(){return{login:false}}<Author v-if="!login"></Author><div v-else>学生或者老师的页面</div>2.问题:无论成功或者失败,都是走成功的回调函数,
页面切换
我做的后台页面较少,所以不需要用到路由
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);
})
更多推荐
所有评论(0)