vue3+TS+pinia+cookies+axiox 实现简单登录的持久化

目录

完整项目请访问

一.各页面完整代码

1.浏览器缓存相关设置

2.pinia状态管理应用

3.request请求/响应拦截

4.路由守卫

5.登录页代码

6.header登录部分代码

二.部分代码截取

1.login登录页

2.header部分


完整项目请访问

gitee:vue3-TS-model: 用于从零搭建模板使用 (gitee.com)

github:vue3-TS-model: 用于从零搭建模板使用 (gitee.com)

一.各页面完整代码

1.浏览器缓存相关设置

这一部分使用了localstorage,session,cookies数据缓存方式

import Cookies from 'js-cookie';

/**
 * window.localStorage 浏览器永久缓存
 * @method set 设置永久缓存
 * @method get 获取永久缓存
 * @method remove 移除永久缓存
 * @method clear 移除全部永久缓存
 */
export const Local = {
	// 设置永久缓存
	set(key: string, val: any) {
		window.localStorage.setItem(key, JSON.stringify(val));
	},
	// 获取永久缓存
	get(key: string) {
		let json: any = window.localStorage.getItem(key);
		return JSON.parse(json);
	},
	// 移除永久缓存
	remove(key: string) {
		window.localStorage.removeItem(key);
	},
	// 移除全部永久缓存
	clear() {
		window.localStorage.clear();
	},
};

/**
 * window.sessionStorage 浏览器临时缓存
 * @method set 设置临时缓存
 * @method get 获取临时缓存
 * @method remove 移除临时缓存
 * @method clear 移除全部临时缓存
 */
export const Session = {
	// 设置临时缓存
	set(key: string, val: any) {
		if (key === 'token' || key === 'username'){
			const expirationTime = new Date();
      expirationTime.setTime(expirationTime.getTime() + 2 * 60 * 60 * 1000); // 2小时后过期
      return Cookies.set(key, val, { expires: expirationTime });
		} 
		window.sessionStorage.setItem(key, JSON.stringify(val));
	},
	// 获取临时缓存
	get(key: string) {
		if (key === 'token' || key === 'username') return Cookies.get(key);
		let json: any = window.sessionStorage.getItem(key);
		return JSON.parse(json);
	},
	// 移除临时缓存
	remove(key: string) { 
		if (key === 'token' || key === 'username') return Cookies.remove(key);
		window.sessionStorage.removeItem(key);
	},
	// 移除全部临时缓存
	clear() {
		Cookies.remove('token');
		Cookies.remove('username');

		window.sessionStorage.clear();
	},
};

2.pinia状态管理应用

这一部分用于存储登陆后获取的一些信息,用于全局

// 在 src/store/index.js 中创建一个简单的 store
import { UserInfoState } from '@/api/login/types';
import { defineStore } from 'pinia'

interface State {
  userForm: UserInfoState;
  isLogin:boolean;
}

export const useMyStore = defineStore('myStore', {
  state: (): State => ({
    userForm: {
      user: '',
      ID: '',
      age: '',
      sex: ''
    },
    isLogin:false
    // 其他状态
  }),
  actions: {
    // 动作
    setUserInfo(data:UserInfoState) {
      this.userForm = data
    },
    setIsLogin(data:boolean) {
      this.isLogin = data
    },

  },
})

3.request请求/响应拦截

import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Session } from '@/utils/storage';

// 配置新建一个 axios 实例
const service = axios.create({
	baseURL: 'https://www.fastmock.site/mock/b9536a1dea3fe4daeec18bc365e14a18/api',
	timeout: 50000,
	headers: { 'Content-Type': 'application/json' },
});

// 添加请求拦截器
service.interceptors.request.use(
	(config) => {
		// 在发送请求之前做些什么 token
		if (Session.get('token')) {
			(config.headers).common['token'] = `${Session.get('token')}`;
		}
		return config;
	},
	(error) => {
		// 对请求错误做些什么
		return Promise.reject(error);
	}
);

// 添加响应拦截器
service.interceptors.response.use(
	(response) => {
		// 对响应数据做点什么
		const res = response.data;
		if (res.code && res.code !== '2000') {
			// `token` 过期或者账号已在别处登录
			if (res.code === 401 || res.code === "4001") {
				Session.clear(); // 清除浏览器全部临时缓存
				window.location.href = '/'; // 去登录页
				ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
					.then(() => {})
					.catch(() => {});
			}
			return response.data;
			// return Promise.reject(service.interceptors.response);
		} else {
			return response.data;
		}
	},
	(error) => {
		// 对响应错误做点什么
		if (error.message.indexOf('timeout') != -1) {
			ElMessage.error('网络超时');
		} else if (error.message == 'Network Error') {
			ElMessage.error('网络连接错误');
		} else {
			if (error.response.data) ElMessage.error(error.response.statusText);
			else ElMessage.error('接口路径找不到');
		}
		return Promise.reject(error);
	}
);

// 导出 axios 实例
export default service;

4.路由守卫

// 导入router所需的方法
import { createRouter, createWebHashHistory } from 'vue-router'

// 导入路由页面的配置
import routes from './routes'
import { Session } from '@/utils/storage'
import { useMyStore } from '@/stores/states'

// 路由参数配置
const router = createRouter({
    // 使用hash(createWebHashHistory)模式,(createWebHistory是HTML5历史模式,支持SEO)
    history: createWebHashHistory(),
    routes: routes,
})

// 全局前置守卫,这里可以加入用户登录判断
router.beforeEach((to, from, next) => {
    if(Session.get('token') && (from.path === '/' || to.path === '/index')){
        useMyStore().setIsLogin(true)
    }
    // 继续前进 next()
    // 返回 false 以取消导航
    next()
})

// 全局后置钩子,这里可以加入改变页面标题等操作
router.afterEach((to, from) => {
    const _title = to.meta.title
    if (_title) {
        window.document.title = String(_title)
    }
})

// 导出默认值
export default router

5.登录页代码







 

6.header登录部分代码







二.部分代码截取

1.login登录页

// 定义登录逻辑
const login = () => {
  let data: LoginState = {
    username: state.formData.username,
    password: state.formData.password,
    code: state.formData.code
  }
  useLoginApi.login(data)
    .then((res) => {
      console.log(res);
      // 登录成功后的处理逻辑
      Session.set('token', res.data.token)
      Session.set('username', res.data.userInfo.user)
      useUserInfoStore.setUserInfo(res.data.userInfo)
      useUserInfoStore.setIsLogin(true)

      router.push({
        name: 'index'
      })
    })
    .catch((err) => {
      console.log(err);
    })
}

2.header部分


// 退出登录
const logout = (pageUrl: string) => {
  console.log('logout', pageUrl);

  // 弹出确认对话框
  ElMessageBox.confirm(
    '确认退出登录?',
    '提示',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
    .then(() => {
      // 清空本地存储
      Session.clear();
      // 设置全局状态中的登录状态为 false
      useMyStore().setIsLogin(false);
      // 跳转到指定页面
      router.push({ name: pageUrl });

      // 提示退出成功
      ElMessage({
        type: 'success',
        message: '退出成功!',
      });
    })
    .catch(() => {
      // 提示取消退出
      ElMessage({
        type: 'info',
        message: '取消退出!',
      });
    });
};

你可能感兴趣的:(vite创建vue3,TS项目实例,前端)