vue3+element-plus+登录逻辑token+环境搭建
vue3+element-plus+登录逻辑token环境搭建
安装脚手架工具
1 npm i @vue/cli@4.5.13 -g
验证是否安装成功
1 vue -V # 输出 @vue/cli 4.5.13
脚手架初始化目录结构
1 vue create jd-shop-manager

手动配置需要的功能






进入到项目目录
1 cd jd-shop-manager
附加其他依赖
1 npm i axios element-plus pinia -S
运行项目
1 npm run serve
浏览器输入localhost:8080查看效果

配置第三方库,main.js根目录
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 1. 引入 { createPinia }
import { createPinia } from 'pinia'
import router from './router'
createApp(App)
// 2. 安装插件
.use(createPinia())
.use(ElementPlus)
.use(router)
.mount('#app')
创建文件utils/request.js,关于token认证,
- 获取token
- 保存token
- 后续携带toke
import Axios from 'axios';
const req = Axios.create({
// baseURL:'http://localhost:3000' // 跨域
baseURL:'/api' // 实例独特的表示,走代理解决跨域
});
// 拦截器 = 公共行为: 请求loading 响应关闭loading
// 响应的错误常规处理 401 => 无权访问, 路由跳转到401页面
// 请求时 如果有token, 自动添加到请求头,响应时自动存储token
req.interceptors.response.use((response)=>{
// response:{ data,config:{ headers } }
if (response.data.token) {
// 保存到本地存储: sessionStorage, localStorage
sessionStorage.setItem('token',response.data.token)
}
// 处理响应的业务异常
return response;
},(err)=>{
// 4xx 5xx异常
// 非业务范畴的通用异常提示
console.log('响应异常:',err)
})
// 请求使用token
req.interceptors.request.use((config)=>{
const token = sessionStorage.getItem('token');
if (token) {
config.headers.token = token;
}
return config;
});
export default req;
Axios,vue.config.js配置代理,去玩微博里面找
创建文件api/user.js
1
// 引入3000端口的实例
import req from '@/utils/request';
export const test = ()=> {
return req.get('/')
}
export const login = (data)=>{
return req({
url:'/login',
method:'post',
data
})
}
export const loadMenu = ()=>{
return req.get('/menus/build')
}
pinia插件配置,创建文件store/user.js
// 3. 定义一个Store
// 3.1 引入定义Store的函数
import { defineStore } from 'pinia';
// 4.按约定俗成 返回useXxx
export const useUser = defineStore({
id:'user',
state(){
return {
userInfo:{},
userMenu:[]
}
},
// 修改方式
actions:{
setUserInfo(user){
this.userInfo = user;
},
// { userMenu:值 }
setUserMenu(patchData) {
this.$patch(patchData);
}
}
})
配置路由文件
创建router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
import { useUser } from '@/store/user'
import { loadMenu } from '@/api/user';
import Layout from '@/views/Layout.vue'
function checkLogin() {
// 前端验证token有效性
// 请求后端验证token有效性
return window.sessionStorage.getItem('token');
}
function asyncRouteHandler(routes) {
return routes.map(route=>{
// 判断Componet是不是一个布局组件名 Layout
if (route.component === 'Layout') {
route.component = Layout;
} else {
const compPath = route.component;
route.component = () => import(`../views/${compPath}.vue`)
}
// 处理children
if (route.children && route.children.length > 0) {
route.children = asyncRouteHandler(route.children);
}
// 返回route
return route;
});
}
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
async function loadAsyncMenu(to, next) {
const user = useUser();
// 动态根据用户的角色或者id拿到他能看到的页面,并生成路由
const res = await loadMenu();
console.log(res.data,'路由数据'); // []
const asyncRoutes = asyncRouteHandler(res.data);
// Todo: 保存菜单到pinia
user.setUserMenu({ userMenu:res.data });
// 添加到原来的路由对象中
asyncRoutes.forEach(r=>{
router.addRoute(r);
});
// 重新进入路由 , replace避免多一个上一步
next({...to,replace:true});
}
// 路由守卫, 在每次确认路由和跳转页面之前
router.beforeEach((to, from, next) => {
const user = useUser();
// next(); 放行
// next(route对象|| stringPath ); 重定向
// next(false); 取消用户导航行为
// 不调用 白屏卡住
// to 代表当前的访问路径 from 代表从哪里来 to|from.path 具体路径
// 访问白名单(可以是个数组)不需要验证 /login
if (to.path === '/login' || to.path === '/register') {
// 不验证/不重定向 => 放行
return next();
}
// 需要验证
if (!checkLogin()) {
// 去登录
// return next('/login?redirect='+ to.path);
return next({
name: 'Login', query: {
redirect: to.path
}
});
}
// 登录了, 判断是否已生成路由
if (user.userMenu && user.userMenu.length > 0) {
return next(); // 放行
}
// 没有菜单,加载菜单
loadAsyncMenu(to, next)
})
export default router
实现一个基于ElementPlus的基础登录框
创建Login.vue中写
<template>
<el-form label-width="80px" ref="formRef" :model="form" :rules="rules">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="form.password"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="submit(formRef)">提交</el-button>
<el-button @click="reset(formRef)">重置</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
//基本 内部多属性
import { ref, reactive } from 'vue';
import { test, login } from '@/api/user'
import { useUser } from '@/store/user';
import { useRoute,useRouter } from 'vue-router'
// 一定要在方法内使用 useUser
const user = useUser(); // 相当于setup方法
const route = useRoute();
const router = useRouter();
// 单向数据输出,双向数据绑定,还需要API方法的调用
const formSize = ref('default'); // formSize.value
const ruleForm = reactive({ // 直接跟原始结构一样 ruleForm.username
username: 'Hello123',
password: '123456'
})
// 需要改变的复杂对象, reactive, 性能优化,直接使用固定对象
const rules = {
username: [
{ required: true, message: '必须输入用户名', trigger: 'blur' },
],
password: [
{ required: true, message: '必须输入密码', trigger: 'blur' },
]
}
// 获取页面组件对象
const ruleFormRef = ref();
// const doSubmit = () => {
// // 需要注意
// ruleFormRef.value.validate((valid, fields) => {
// if (valid) {
// console.log('submit!')
// } else {
// console.log('error submit!', fields)
// }
// })
// }
// 传递参数的方式
const doSubmit = (form) => {
// 需要注意
form.validate(async (valid, fields) => {
if (valid) {
console.log('submit!');
// login
let res = await login(ruleForm);
console.log(res, '测试数据');
// 登录成功
// 修改Pinia里面的数据状态
// user.setUserInfo({
// username: 'Green'
// });
// 跳转到首页 或者 [之前地址栏的页面] 路由参数redirect
router.push(route.query.redirect || '/');
} else {
console.log('error submit!', fields)
}
})
}
样式篇
- 初始化样式

html,body { height: 100%; width: 100%;}a { text-decoration: none; }ul {padding:0; }li {list-style: none; }html,body,h1,h2,h3,h4,h5,h6 { padding:0; margin:0; }span {display:inline-block; }
vue3+element-plus+登录逻辑token+环境搭建的更多相关文章
- 【Vue3+Express实战】项目开发环境搭建
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- [精华][推荐]CAS SSO 单点登录框架学习 环境搭建
1.了解单点登录 SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...
- ssh运行环境搭建及测试
一.运行环境 1.Spring环境 Spring是一站式开发框架,在SSH中主要有以下作用,就像一个大管家: 控制反转(Inversion of Control):类不再自己进行类创建,而是交给Spr ...
- web 单一平台登录逻辑
单点登录逻辑token=cookie('login_token');serverToken=get(token);if(serverToken!='注销'){ set('userid_已登录token ...
- ASP.NET WebAPI 双向token实现对接小程序登录逻辑
最近在学习用asp.net webapi搭建小程序的后台服务,因为基于小程序端和后台二者的通信,不像OAuth(开放授权),存在第三方应用.所以这个token是双向的,一个是对用户的,一个是对接口的. ...
- Shrio00 Shiro认证登录、权限管理环境搭建
基础环境准备: JDK -> java version "1.8.0_101" MAVEN -> Apache Maven 3.5.0 1 导入依赖 mysql驱动 m ...
- Windows 环境搭建 PostgreSQL 逻辑复制高可用架构数据库服务
本文主要介绍 Windows 环境下搭建 PostgreSQL 的主从逻辑复制,关于 PostgreSQl 的相关运维文章,网络上大多都是 Linux 环境下的操作,鲜有在 Windows 环境下配置 ...
- Struts2开发环境搭建,及一个简单登录功能实例
首先是搭建Struts2环境. 第一步 下载Struts2去Struts官网 http://struts.apache.org/ 下载Struts2组件.截至目前,struts2最新版本为2.3.1. ...
- 1、IOS开发--iPad之仿制QQ空间(登录界面搭建+登录逻辑实现)
开始搭建登录界面 登录界面效果图: 相关的图片资源下载百度云备份链接: http://pan.baidu.com/s/1o71cvMU 密码: 2h7e 步骤开始: 设置辅助窗口的位置在下方 快捷键o ...
随机推荐
- 使用idea remote 开发体验
本地使用idea开发最不好的一个体验就是打开稍大的工程就非常的卡,怎么调参数都没用,现在idea推出了idea remote就赶紧来体验下. 使用方式 除了idea不需要额外下载什么包,但是因为rem ...
- 未完待续【java】JavaEE学习路线总览
这个博客会详细介绍各种技术的知识点,从零基础到入门,充当引路的作用. 同时也会发布一些Swift语言.c#语言.Xcode开发的学习笔记.一些阅读的笔记(部分读书笔记无法发布). 目前1-43的Jav ...
- 使用puppeteer生成pdf与截图
之前写过一篇 vue cli2 使用 wkhtmltopdf 踩坑指南,由于wkhtmltopdf对vue的支持并不友好,而且不支持css3,经过调研最终选择puppeteer,坑少,比较靠谱. 一. ...
- 【面试题】js实现将excel表格copy到页面
js实现将excel表格copy到页面 点击打开视频讲解更加详细 其实最核心的技术,还是copy的是我们粘贴板上的数据 就像平常怎么粘贴复制其他的数据一样,只是我们在excel粘贴的是一个表格数据 这 ...
- KingbaseES V8R6兼容Oracle的exp-imp导出导入工具使用
说明: KingbaseES V8R6版本中的兼容Oracle的exp-imp导入导出工具,支持完全模式.用户模式和表模式的导出功能. 本次案例数据库版本: test=# select version ...
- KingbaseES V8R6集群维护案例之--修改securecmdd工具服务端口
案例说明: 在一些生产环境,为了系统安全,不支持ssh互信,或限制root用户使用ssh登录,KingbaseES V8R6可以使用securecmdd工具支持主机之间的通讯.securecmdd工具 ...
- centos7部署k8s(1master1node)
〇.前言 就想多学学罢了 准备环境: centos7 master 8GB 172.26.130.204 centos7 node 8GB 172.26.130.205 yum源就阿里源就好... 一 ...
- Lua 支持虚函数的解决方案
概述 lua本身没有提供类似C++虚函数机制,调用的父类方法调用虚函数可能会出现问题. 问题分析 分析这段代码和输出 local Gun = {} -- 示例,实际应用还要考虑构造,虚表等情况 fun ...
- 生信云实证Vol.12:王者带飞LeDock!开箱即用&一键定位分子库+全流程自动化,3.5小时完成20万分子对接
LeDock是苏黎世大学Zhao HongTao在博士期间开发的一款分子对接软件,专为快速准确地将小分子灵活对接到蛋白质而设计.LeDock优于大部分商业软件,在Astex多样性集合上实现了大于90% ...
- 0.web理解
web前后端 网站的前端:通过用户肉眼看到的网站的布局内容,对网站的操作的功能,可以让用户可以直接接触与操作的部分. 用户通过访问前端的功能,前端分为 静态功能+动态功能 静态功能:静态功能则不会和后 ...