Vue_Router
认识路由
-
在架构一个网络时,非常重要的两个设备
-
路由器主要维护的是一个映射表 ip地址-真实电脑的mac地址
-
映射表会决定路由的流向
-
web的发展经历了这些阶段
-
后端路由阶段:服务器直接渲染好对应的HTML 页面,返回给客户端进行展示 url->page
一一对应
-
前后端分离阶段:每次请求涉及到静态资源服务器获取,然后在前端对这些请求回来我的资源
进行渲染,后端只提供api
-
单页面富应用(SPA):single page webapplication ,通过不同的路径渲染不同的组件,存在路径
和组件的映射关系,为了限制随便访问,可以通过hash 和history
-
url的hash
- url 的hash也就是锚点,本质上改变window.location的href的属性
- 我们可以通过直接赋值location.hash来改变href,但页面不刷新
- hash的优势是兼容性好,在老版本IE中都可以运行,但是缺陷是#显示不像一个真实路径
- 通过location.hash获取hsah,window的hashchange事件,监听hash的改变
html5的history
- history接口是html5新增的,它有六种模式改变而不刷新页面
- replaceState:替换原来的路径,不可返回
- pushState:使用新路径,入栈操作
- popState:路径回退
- go:向前或向后改变路径 go(-1) go(1)
- forward:向前改变路径
- back:向后改变路径
- 通过location.pathname获取路径,history不能用本地的
认识vue-router
-
目前前端流行的三大框架都有自己的router
-
Angular的ngRouter
-
React的ReactRouter
-
vue的vue-router
-
-
vue-router 是基于路由和组件的
- 路由用于设定访问路径,将路径和组件映射起来
- 在yue-router 的单页面应用中,页面的路径改变就是组件的切换
-
安装
npm install vue-router@4
-
使用步骤
- 创建路由组件的组件
import { createApp } from 'vue' import router from './router' import App from './App.vue' const app= createApp(App) app.use(router) app.mount("#app")
- 配置路由映射:组件和路由映射关系的routes数组
const routes=[ // 设置重定向 {path:"/",redirect:"/home"}, {path:'/home',component:Home}, {path:'/about',component:About} ];
- 通过createRouter创建路由对象,并传入routes和history
//创建路由的对象router const router =createRouter({ routes:lan_routes, //routes es6特性 history:createWebHistory() });
- 使用路由通过和
<router-link to="/home" active-class="select" replace>首页</router-link> <router-link to="/about" active-class="select" >关于</router-link> <router-link to="/user/why/id/1" active-class="select" >用户</router-link> <!-- to属性是一个字符串,replace:会调用router.replace ,activite_class 可以设置选中 可以修改默认名字 exact-active-class:链接精准激活时,应用于渲染<a>的class ,默然是router-exact-active 懒加载:用到再加载 动态匹配:可以进行拼接 --> <router-view></router-view>
懒加载
const lan_routes=[
{
path:"/",
redirect:"/home"
},
{
path:'/home',
name:"home",
component: ()=> import(/* webpackChunkName:"home-chunk" */"../components/Home.vue"),
meta:{
//源数据 name:路由独一无二的名称
},
children:[
{
path:"",
redirect:"/home/msg"
},
{
path:"msg",
component:()=>import("../components/HomeMsg.vue")
},
{
path:"shops",
component:()=>import("../components/HomeShop.vue")
}
]
},
{
path:'/about',
name:"about",
component:()=> import(/* webpackChunkName:"about-chunk" */"../components/About.vue")
},
{
//动态匹配 :username
path:'/user/:username/id/:id',
name:"user",
component:()=> import(/* webpackChunkName:"user-chunk" */"../components/User.vue")
},
{
//任意匹配 /:pathMatch(.*) /:pathMatch(.*) * /斜杠会作为分割符 分割
path:"/:pathMatch(.*)",
component:()=>import("../components/NotFound.vue")
}
];
//创建路由的对象router
const router =createRouter({
routes:lan_routes,
//routes es6特性
history:createWebHistory()
});
动态路由的基本匹配
{
//动态匹配 :username
path:'/user/:username/id/:id',
name:"user",
component:()=> import(/* webpackChunkName:"user-chunk" */"../components/User.vue")
}
NotFound
{
//任意匹配 /:pathMatch(.*) /:pathMatch(.*) * /斜杠会作为分割符 分割
path:"/:pathMatch(.*)",
component:()=>import("../components/NotFound.vue")
}
路由的嵌套
{
path:'/home',
name:"home",
component: ()=> import(/* webpackChunkName:"home-chunk" */"../components/Home.vue"),
meta:{
//源数据 name:路由独一无二的名称
},
children:[
{
path:"",
redirect:"/home/msg"
},
{
path:"msg",
component:()=>import("../components/HomeMsg.vue")
},
{
path:"shops",
component:()=>import("../components/HomeShop.vue")
}
]
},
代码的页面跳转
<button>首页</button>
<span @click="jumpToAbout()">关于</span>
<script>
import {useRouter} from "vue-router";
export default {
name: 'App',
components: {
},
methods:{
// jumpToAbout(){
// //获取router对象
// console.log("jj");
// this.$router.push("/about");
// }
},
setup(){
const router =useRouter();
const jumpToAbout=()=>{
// router.push("/about");
router.push({
path:"/about",
query:{
username:"123",
age:16
}
})
}
return {
jumpToAbout
}
}
}
routre-link的v-slot
<!-- props:
href 跳转的链接
route对象
navigate导航函数
custom:自定义
isActive:当前是否活跃
isExactActive:是否是精确的活跃
-->
<router-link to="/home" active-class="select" replace v-slot="props" custom>
<nav-bar title="首页"/>
<button>hahhahha</button>
<button @click="props.navigate">首页</button>
<button>{{props.href}}</button>
<button>{{props.route}}</button>
<button>{{props.navigate}}</button>
<span :class="{'active':props.isActive}">{{props.isActive}}</span>
<span :class="{'active':props.isExactActive}">{{props.isExactActive}}</span>
</router-link>
router-view的v-slot
<router-view v-slot="props">
<!-- v-solt 作用域插槽 用props来传输 -->
<transition name="why">
<!-- keep-alice 开启缓存 -->
<keep-alive>
<component :is="props.Component"></component>
</keep-alive>
</transition>
</router-view>
<!--直接对对象进行解构 也有 route对象 -->
<router-view v-slot="{Component}">
<transition name="why">
<!-- keep-alice 开启缓存 -->
<keep-alive>
<component :is="Component"></component>
</keep-alive>
</transition>
</router-view>
动态添加路由
//不同角色拥有不同的路由 根据菜单动态添加路由
const active_routes=[];
if(管理员){
router.addRoute({
path:"/order",
component:()=>import("../components"/);
})
}
// 一级路由
const categoryRoute={
path:"/category",
component: ()=>import("../components/Category.vue")
}
router.addRoute(categoryRoute);
// 二级路由
router.addRoute("home",{
path:"moment",
component:()=>import("../components/HomeMoment.vue")
})
//三级路由
//根据 name添加路由
动态删除路由
- 添加一个name相同路由
- 通过removeRoute方法,传入名称
- 通过addRoute方法的返回值回调
- route.hasRoute():检出路由是否存在
- route.getRoute:获取所有路由
路由导航守卫
- vue-router提供的导航守卫主要用来通过跳转或取消的方式来守卫导航
- 全局的前置守卫beforeEach
// to: route 对象,即将跳转到的路由对象
// from :route 对象,从哪个路由对象导航来的
//返回值 :false 不进行导航 undefine 返回undefined 进行默认导航 3:字符串:跳转路径 return "/about"
//对象 :router.push({path:,query:}) vue2中的next容易出现多次调用
let counter=0;
router.beforeEach((to,from)=>{
const token=window.localStorage.getItem("token");
if(!token)
return "/login"
})
<script>
import {useRouter} from "vue-router";
export default {
setup(){
const router=useRouter();
const loginClick=()=>{
window.localStorage.setItem("token","why");
router.push({
path:"/home"
})
}
return {
loginClick
}
}
}
2.解析过程
- 导航先被触发
- 在失活组件力调用beforeRouteleave
- 调用全局的beforeEach
- 在重用组件中调用beforeRouteUpdate
- 在路由配置里调用beforeEnter
- 解析异步路由组件
- 在被激活的组件里调用beforeRouteEnter
- 调用全局的beforeResolve
- 导航被确认
- 调用全局的afterEach钩子
- 触发dom更新
- 调用beforeRouteEnter 守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数
传入。