大事件
需求
学习路径
环境准备
创建Vue工程:
npm init vue@latest
安装依赖
Element-Plus:
npm install element-plus --save
Axios:
npm install axios
Sass:
npm install sass -D
目录调整
- 删除components下面自动生成的内容
- 新建目录api、utils、views
- 将资料中的静态资源拷贝到assets目录下
- 删除App.vue中自动生成的内容
功能开发
开发步骤
数据绑定时,参考接口文档给属性起名。
表单校验时,
el-form标签上通过rules属性,绑定校验规则;
el-form-item标签上通过prop属性,指定校验项。
跨域问题
由于浏览器的同源策略
限制,向不同源(不同协议、不同域名、不同端口)发送ajax请求会失败。
解决:配置代理
- 将
request.js
中const baseURL = 'http://localhost:8080';
修改为const baseURL = '/api';
,相当于:http://localhost:5173/api - 在
vite.config.js
修改
优化axios响应拦截器
消息提示
import { ElMessage } from 'element-plus'
ElMessage.error(result.data.msg ? result.data.msg : '服务异常');
ElMessage.success(result.msg ? result.msg : '登录成功')
路由
- 路由,决定从起点到终点的路径的进程
- 在前端工程中,路由指的是根据不同的访问路径,展示不同组件的内容。
- Vue Router是Vue.js的官方路由,它与Vue.js深度集成,让Vue.js构建单页面应用变得更加轻而易举。
Vue Router
安装Vue Router:
npm install vue-router@4
在src/router/index.js中创建路由器,并导出
//index.js //导入vue-router import { createRouter, createWebHistory } from 'vue-router' //导入组件 import LoginVue from '@/views/Login.vue' import LayoutVue from '@/views/Layout.vue' //定义路由关系 const routes = [ { path: '/login', component: LoginVue }, { path: '/', component: LayoutVue } ] //创建路由器 const router = createRouter({ history: createWebHistory(), //vue中有history和哈希两种路由模式 routes: routes }); export default router
在vue应用实例中使用vue-router
//main.js import router from '@/router' //index.js。这样名字的js文件在导入时,可以不写文件名,只要定位到文件所在的文件夹即可,使用起来很方便 app.use(router)
声明router-view标签,展示组件内容
//App.vue <template> <router-view></router-view> </template>
子路由
当用户点击左侧的菜单时,右侧主区域的内容需要发生变化,将来每切换一个菜单,右侧需要加载对应组件的内容进行展示,像这样的场景也需要使用路由来完成
由于这些组件都需要在Layout.vue中展示, 而Layout.vue本身已经参与了路由,因此需要在Layout.vue中通过子路由的方式来完成组件的切换
提供菜单对应的组件
配置子路由
//定义路由关系 const routes = [ { path: '/login', component: LoginVue }, { path: '/', component: LayoutVue, redirect: '/article/manage', children: [ { path: '/article/category', component: ArticleCategoryVue }, { path: '/article/manage', component: ArticleManageVue }, { path: '/user/info', component: UserInfoVue }, { path: '/user/avatar', component: UserAvatarVue }, { path: '/user/resetPassword', component: UserResetPasswordVue } ] } ]
在Layout.vue组件的右侧中间区域,添加router-view标签
菜单项el-menu-item设置index属性,设置点击后跳转的路由路径
Pinia状态管理库
Pinia是Vue的专属状态管理库,它允许跨组件或页面共享状态。
安装pinia:
npm install pinia
在vue应用实例中使用pinia
import { createPinia } from 'pinia' const pinia = createPinia() app.use(pinia)
在src/stores/token.js中定义store
import { defineStore } from "pinia"; import {ref} from 'vue'; /* defineStore参数描述: 第一个参数:给状态起名,具有唯一性 第二个参数:函数,可以把定义该状态中拥有的内容 defineStore返回值描述: 返回的是一个函数,将来可以调用该函数,得到第二个参数中返回的内容 */ export const useTokenStore = defineStore('token',()=>{ //1.定义描述token const token = ref('') //2.定义修改token的方法 const setToken = (newToken)=>{ token.value = newToken } //3.定义移除token的方法 const removeToken = ()=>{ token.value='' } return { token,setToken,removeToken } })
在组件中使用store
在需要使用状态的地方,导入@/stores/*.js , 使用即可
在Login.vue中导入@/stores/token.js, 并且当用户登录成功后,将token保存pinia中
//导入token状态 import { useTokenStore } from '@/stores/token.js' //调用useTokenStore得到状态 const tokenStore = useTokenStore(); //用于登录的事件函数 const login = async () => { let result = await loginService(registerData.value) //保存token tokenStore.setToken(result.data) ElMessage.success('登录成功!') router.push('/') }
在article.js中导入@/stores/token.js, 从pinia中获取到存储的token,在发起查询文章分类列表的时候把token通过请求头的形式携带给服务器
//导入@/stores/token.js import { useTokenStore } from '../stores/token' //文章分类列表查询 export const articleCategoryListService = () => { //获取token状态 const tokenStore = useTokenStore() //通过请求头Authorization携带token return request.get('/category', { headers: { 'Authorization': tokenStore.token } }) }
Axios请求拦截器
当进入主页后,将来要与后台交互,都需要携带token,如果每次请求都写这样的代码,将会比较繁琐,此时可以将携带token的代码通过请求拦截器统一处理
在 src/util/request.js中
//导入token状态
import { useTokenStore } from '@/stores/token.js';
//添加请求拦截器
instance.interceptors.request.use(
(config)=>{
//在发送请求之前做什么
let tokenStore = useTokenStore()
//如果token中有值,在携带
if(tokenStore.token){
config.headers.Authorization=tokenStore.token
}
return config
},
(err)=>{
//如果请求错误做什么
Promise.reject(err)
}
)
Pinia持久化插件-persist
- 由于pinia是内存存储,当刷新页面的时候pinia中的数据会丢失
- Persist插件支持将pinia中的数据持久化到sessionStorage和localStorage中
使用
安装persist:
npm install pinia-persistedstate-plugin
在pinia中使用persist
import { createPersistedState } from 'pinia-persistedstate-plugin' const persist = createPersistedState(); pinia.use(persist);
定义状态Store时指定持久化配置参数
//token.js { persist: true //持久化存储 }
未登录统一处理
在后续访问接口时,如果没有登录,则前端不携带token,后台服务器会返回响应状态码401,代表未登录,此时可以在axios的响应拦截器中,统一对未登录的情况做处理
//request.js
import router from '@/router'
//添加响应拦截器
instance.interceptors.response.use(
result => {
//如果业务状态码为0,代表本次操作成功
if (result.data.code == 0) {
return result.data;
}
//代码走到这里,代表业务状态码不是0,本次操作失败
ElMessage.error(result.data.message || '服务异常');
return Promise.reject(result.data);//异步的状态转化成失败的状态
},
err => {
//如果响应状态码时401,代表未登录,给出对应的提示,并跳转到登录页
if(err.response.status===401){
ElMessage.error('请先登录!')
router.push('/login')
}else{
ElMessage.error('服务异常');
}
return Promise.reject(err);//异步的状态转化成失败的状态
}
)