vue+ts下集----ts配置路由、路由守卫、数据交互-axios、登录验证逻辑、状态管理
### ts配置路由
①安装:npm i vue-router -S
②src下新建pages/Home.vue(还有Goods.vue、Detail.vue等页面):
<template> <div class="home"> <h2>首页</h2> </div> </template> <script lang="ts"> import Vue from 'vue'; import {Component} from "vue-property-decorator"; @Component({}) export default class Home extends Vue{ } </script>
③src下新建plugins/router.ts:(注意Reg.vue和Detail.vue分别是以import和require的方式实现路由懒加载)
import Vue from "vue"; import VueRouter from "vue-router"; Vue.use(VueRouter);// 安装插件 import Home from "../pages/Home.vue"; import Goods from "../pages/Goods.vue"; import User from "../pages/User.vue"; import Login from "../pages/Login.vue"; import NoPage from "../pages/NoPage.vue"; let routes=[ {path:"/home",component:Home}, {path:"/goods",component:Goods}, {path:"/user",component:User}, {path:"/login",component:Login}, {path:"/reg",component:()=>import("../pages/Reg.vue")}, {path:"/detail",component:(resolve:any)=>{require(["../pages/Detail.vue"],resolve)}}, {path:"*",component:NoPage}, {path:"/",redirect:"/home"}, ]; let router=new VueRouter({ mode:"history", routes }); export default router;
④main.js中引入router并注册:
import router from "./plugins/router" new Vue({ render: h => h(App), router }).$mount('#app')
⑤App.vue中开辟路由空间:
<router-view></router-view>
### 路由守卫
router.ts中:
/* 全局守卫 */ router.beforeEach((to,from,next)=>{ console.log("全局前置守卫") next(); }) router.afterEach((to,from)=>{ console.log("全局后置守卫") }) // 路由独享守卫 {path:"/user",component:User,beforeEnter: (to:Route, from:Route, next:Function) => { console.log("路由独享前置守卫") next(); }},
注意:设置路由独享守卫时,定义的Route类型是ts自动引入的(import VueRouter, { Route } from "vue-router";)
组件内部守卫:(注意这里的Route类型是手动引入的)
(1)User.vue中:
import {Route} from "vue-router"; @Component({ /* 这里写自定义指令、过滤器、守卫钩子函数 */ beforeRouteEnter (to:Route, from:Route, next:Function) { // 由于写在装饰器中,钩子函数可以自动推测出to、from、next的类型,所以可以加类型也可以不加 console.log("组件内前置守卫") next(); } })
(2)Reg.vue中:
import {Route} from "vue-router"; @Component({ beforeRouteLeave (to:Route, from:Route, next:Function) { console.log("组件内后置守卫") next(); } })
### 数据交互-axios
安装:npm i axios @types/axios -S
注意:不是所有的插件都带有类型声明文件,只有类型声明文件才能保证支持ts,没有类型声明文件的插件需要安装类型声明文件。
(1)axios初步使用:
①public下新建data/user.json:
{ "data":[ {"username":"wxm"} ] }
②Home.vue中:
import axios from "axios"; export default class Home extends Vue{ mounted():void { axios({ url:"/data/user.json" // public中的数据可以直接访问 }).then( res=>console.log(res.data) ) } }
(2)访问json-server数据:
需要先将json-server开启数据服务,再设置url:url:"http://localhost:3000/data"
(3)访问tiantian-api数据:
①开启tiantian-api数据服务:npm run start
②设置跨域代理(根目录下新建vue.config.js):
module.exports={ devServer:{ proxy:{ "/v3":{ target:"http://localhost:3000", changeOrigin:true } } } }
③代理地址替代原地址:
url:"/v3/homepage"
(4)axios拦截器:
①plugins下新建axios.ts:
import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; import router from './router'; import { TUser } from '@/types'; //请求拦截器 axios.interceptors.request.use((config:AxiosRequestConfig):AxiosRequestConfig=>{ /* 抓取token,携带到响应头 显示loading */ let user:TUser=window.localStorage.getItem("user"); user=user?JSON.parse(user):""; config.headers={token:user?.token}// 携带到请求头 return config; },(error)=>{ return Promise.reject(error) }) //响应拦截器 axios.interceptors.response.use((response:AxiosResponse<any>):AxiosResponse<any>=>{ /* token过期,跳转login,保留当前地址 关闭loading */ // 判断如果有错误(token过期),并且当前路径不是login,则跳转到login页面,并且将当前的全路径带过去 if(response.data.err==2 && !router.currentRoute.fullPath.includes("/login")){ router.push({path:"/login",query:{path:router.currentRoute.fullPath}}); } return response; },(error)=>{ return Promise.reject(error) }) // 对外暴露 export default axios;
②Home.vue中使用时用封装的axios替代原来的axios:
import axios from "../plugins/axios";
(5)将axios挂载到window下:
①src/types/index.ts中:
// 定义全局变量,重定义了Window接口 declare global{ interface Window{ axios(config:AxiosRequestConfig):AxiosPromise<any> } }
②axios拦截器中对外暴露的时候添加:
window.axios=axios;
③main.js中引入:
import "./plugins/axios"
④Home.vue中使用时不用引入任何的axios,直接用window.axios()使用:
mounted():void { window.axios({ url:"/v3/homepage" }).then( res=>console.log(res.data) ) }
### 登录验证逻辑
①axios.ts的响应拦截器中利用router.currentRoute.fullPath可以拿到当前要去往的路由,保留当前地址:
// 判断如果有错误(token过期),并且当前路径不是login,则跳转到login页面,并且将当前的全路径带过去 if(response.data.err==2 && !router.currentRoute.fullPath.includes("/login")){ router.push({path:"/login",query:{path:router.currentRoute.fullPath}}); }
②Login.vue中点击登录时进行请求,如果没有错误,则将token存到localStorage中,并且跳转到响应拦截器中保留的路由:
<button @click="login">登录</button>
export default class Login extends Vue{ public login():void { window.axios({ url:"/api/login", method:"post", data:{username:"chenghao",password:"chenghao123"} }).then( res=>{ if(res.data.err==0){ // 种token到localStorage中 window.localStorage.setItem("user",JSON.stringify(res.data)) // 跳转到之前的页面 this.$router.replace(this.$route.query.path as string) } } ) } }
### 状态管理
①安装:npm i vuex vuex-class -S
未完待续……
分类:
vue
, TypeScript
« 上一篇: vue+ts上集----vue-cli创建项目时注意选中TypeScript、定义组件的三种方式(类式,扩展式,函数式)、函数式组件没有this,它通过props接收父组件传来的值、函数式组件触发事件的方法、类组件中定义props,元数据,实例方法,计算属性,属性检测,ref,自定义指令,过滤器
» 下一篇: vue-day16----拿到登录的token、登录的逻辑、加入购物车、购物车图标上的数量-count、加入购物车的逻辑判断-Dialog对话框(优化)、Cart/index.vue购物车页面数据渲染、Cart/index.vue购物车页面加减法的接口调用、详情页 商品-详情-评价 切换动画、nginx打包
» 下一篇: vue-day16----拿到登录的token、登录的逻辑、加入购物车、购物车图标上的数量-count、加入购物车的逻辑判断-Dialog对话框(优化)、Cart/index.vue购物车页面数据渲染、Cart/index.vue购物车页面加减法的接口调用、详情页 商品-详情-评价 切换动画、nginx打包
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结