2024年Web前端最新Vue全家桶 Vue-router的详细介绍_v-router,2024大厂前端春招面试经历

最后

你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

我特地针对初学者整理一套前端学习资料

前端路线图

vue.js的36个技巧

关于



.home {
color: red;
}


**exact-active-class属性(下面路由嵌套时会讲解)**:



> 
> 链接精准激活时,应用于渲染的 <a> 的 class,默认class是`router-link-exact-active`;
> 
> 
> 




---


### 懒加载分包处理


**当打包构建应用时,JavaScript 包会变得非常大,影响页面加载**:



> 
> 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效;
> 
> 
> 也可以提高首屏的渲染效率;
> 
> 
> 


**其实这里还是我们前面讲到过的webpack的分包知识,而Vue Router默认就支持动态来导入组件**:



> 
> 这是因为component可以传入一个组件,也可以接收一个函数,该函数 需要放回一个Promise;
> 
> 
> 而import函数就是返回一个Promise;
> 
> 
> 



// 使用import函数, 打包时会进行分包处理
routes: [
{
path: “/”,
redirect: “/home”
},
{
path: “/home”,
component: () => import(“…/views/Home.vue”)
},
{
path: “/about”,
component: () => import(“…/views/About.vue”)
}
]



> 
> 打包效果如下
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/f6b3c3733c134e6cb4cdc81b88cd3ea0.png#pic_center)



> 
> 但是我们发现, 打包之后虽然分包了, 但是我们无法分清楚哪一个打包的文件是Home, 哪一个打包的文件是About
> 
> 
> 其实webpack从3.x开始支持对分包进行命名(chunk name)
> 
> 
> 



routes: [
// 添加一个映射关系, 设置默认的展示页面
{
path: “/”,
redirect: “/home”
},
{
path: “/home”,
component: () => import(/* webpackChunkName: ‘home’ */“…/views/Home.vue”)
},
{
path: “/about”,
component: () => import(/* webpackChunkName: ‘about’*/“…/views/About.vue”)
}
]



> 
> 我们再来看一下打包效果
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/c67c000edb7f42a6b1258c272b4b8d26.png#pic_center)


**注意: 在开发中我们使用路由, 一般都是会使用它的懒加载的**




---


### 路由的其他属性



> 
> 前面我使用了路由中的path属性和component属性
> 
> 
> 其实路由中还有name属性和meta属性
> 
> 
> 


**name属性**



> 
> 记录路由独一无二的名称, 在页面跳转的时候也是可以指定name的(用的不多);
> 
> 
> 



routes: [
// 添加一个映射关系, 设置默认的展示页面
{
// name要是独一无二, 唯一的
name: “home”,
path: “/”,
redirect: “/home”
}
]


**meta属性**



> 
> meta属性放一些额外的, 自定义的数据
> 
> 
> 这个自定义数据是可以在其他地方拿到的 (后面用到时在和大家介绍)
> 
> 
> 



{
path: “/”,
redirect: “/home”,
// 自定义的一些数据
meta: {
name: “chenyq”,
age: 18,
height: 1.88
}
}




---


### 动态路由的使用


#### 🍟动态路由基本匹配


**很多时候我们需要将给定匹配模式的路由映射到同一个组件**:



> 
> 例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,我们url需要拼接上用户的ID,但是用户的ID是不同的,意味着我们路径是不能写死的;
> 
> 
> 在Vue Router中,我们可以在路径中使用一个动态字段来实现,我们称之为路径参数;
> 
> 
> 



routes: [
{
// 拼接时上:id表示路径不是写死的, 会有用户传入的id
path: “/user/:id”,
component: () => import(“…/views/User.vue”)
}
]


**在router-link中进行如下跳转**:



用户:123
用户:321


#### 🍟获取动态路由的值



> 
> 上面代码中, 我们虽然实现了/user拼接不同的id显式同一个页面
> 
> 
> 但是我们页面中展示的效果是相同的, 我们需要在User组件中根据不同的用户, 获取到不同的id进行展示
> 
> 
> 


**那么在User中如何获取到对应的值呢?**



> 
> 在template中,直接通过 $route.params获取值;
> 
> 
> 在created中,通过 this.$route.params获取值;
> 
> 
> 在setup中,我们要使用 vue-router库给我们提供的一个hook useRoute;
> 
> 
> * 该Hook会返回一个Route对象,对象中保存着当前路由相关的值;
> 
> 
> 


* **在template模板中,通过 `$route.params`获取值**



User{{ $route.params.id }}


* 在Options API 的 created中,通过 this.$route.params获取值




* **在setup中,我们要使用 vue-router库给我们提供的一个hook `useRoute`;**




#### 🍟NotFound


**对于哪些没有匹配到的路由,我们通常会匹配到固定的某个页面**



> 
> 比如NotFound的错误页面中,这个时候我们可`编写一个动态路由用于匹配所有的页面`;
> 
> 
> 在vue中, 我们可以通过`/:pathMatch(.*)`匹配所有的路径
> 
> 
> 



routes: [
{
path: “/”,
redirect: “/home”
},
{
path: “/home”,
component: () => import(“…/views/Home.vue”)
},
{
path: “/about”,
component: () => import(“…/views/About.vue”)
},
{
path: “/user/:id”,
component: () => import(“…/views/User.vue”)
},
{
// *匹配所有路由的路径
path: “/:pathMatch(.*)”,
component: () => import(“…/views/NotFound.vue”)
}
]


* **当我们匹配不到前面路径的时候, 就会匹配最后一个路径, 显式NotFoun组件**


![在这里插入图片描述](https://img-blog.csdnimg.cn/b8b2af45cf824365bca588fdeb9c9549.png#pic_center)



> 
> 如果我们想要提示用户的什么路径不正确
> 
> 
> 我们可以通过 `$route.params.pathMatch`获取到传入的参数:
> 
> 
> 



Not Found: 您的路径 {{ $route.params.pathMatch }} 不正确,请检查路径是否正确




---


#### 🍟匹配规则加 \*


**刚刚我们通过`/:pathMatch(.*)`匹配所有的路径, 这里还有另一种写法**:



> 
> 注意:我在`/:pathMatch(.*)`后面又加了一个 `*`;
> 
> 
> 



{
// 匹配所有路由的路径
path: “/:pathMatch(.*)*”,
component: () => import(“…/views/NotFound.vue”)
}



> 
> **它们的区别在于解析的时候,是否解析 /**
> 
> 
> 


* 当没有加 \* 号时



{
// 没有加 * 号
path: “/:pathMatch(.*)”,
component: () => import(“…/views/NotFound.vue”)
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/884d5737433748548f5895b42cff4e58.png#pic_center)


* 当加了 \* 号时



{
// 加了 * 号
path: “/:pathMatch(.*)*”,
component: () => import(“…/views/NotFound.vue”)
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/c08f6c6d0c3244a6950a176618aca900.png#pic_center)


### 路由嵌套的使用


**什么是路由的嵌套呢**?



> 
> 目前我们匹配的Home、About、User等都`属于第一层路由`,我们在它们之间可以来回进行切换;
> 
> 
> 


**但是呢,我们Home页面本身,也可能会在多个组件之间来回切换**:



> 
> 比如Home中包括Product、Message,它们可以在Home内部来回切换;
> 
> 
> 这个时候我们就需要使用嵌套路由,在Home中也使用 router-view 来占位之后需要渲染的组件;
> 
> 
> 


**使用嵌套路由, 首先我们需要配置嵌套路由**



> 
> 在我们要配置嵌套路由的映射关系中, 添加children属性
> 
> 
> 下面我用Home组件举例
> 
> 
> 



{
path: “/home”,
component: () => import(“…/views/Home.vue”),
// children中配置home的二级路由
children: [
// 定义默认展示路由
{
path: “/home”,
redirect: “/home/product”
},
{
// 配置HomeProduct组件路由, 二级路径直接写子路径即可
path: “product”, // 相当于: /home/product
component: () => import(“…/views/HomeProduct.vue”)
},
{
// 配置HomeMessage组件路由
path: “message”,
component: () => import(“…/views/HomeMessage.vue”)
}
]
}


* 在Home组件中定义router-view展示二级路由



Home

商品 信息
<!-- 使用router-view站位 -->
<router-view></router-view>



---


**前面我们有说过会在嵌套路由和大家讲解exact-active-class属性**



> 
> exact-active-class属性的默认class是`router-link-exact-active`
> 
> 
> 



> 
> 我们知道active-class属性会匹配当前选中的<router-view>标签
> 
> 
> 而exact-active-class是`精准匹配`当前选中的标签, 这个精准匹配怎么理解呢, 我给大家画一幅图展示
> 
> 
> 


**当上面代码中我们选中首页下面商品的时候**:



> 
> 此时首页和商品都是当前被选中的<router-link>标签, 都会添加上`active-class`属性的默认class`router-link-active`
> 
> 
> 而商品这个<router-link>标签还会额外添加, `exact-active-class`属性的`router-link-exact-active`
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/bf4b9aac6bb34171876deac0b245a8c2.png#pic_center)


### 代码的页面跳转



> 
> 前面我们路由的页面跳转都是通过<router-link>标签完成的
> 
> 
> 但是有时候我们希望通过代码来完成页面的跳转,比如点击的是一个按钮, 点击一个span等等其他元素也实现页面跳转
> 
> 
> 


**如下, 我想通过点击span和button代替刚刚Home组件中的两个<router-link>标签, 那么我可以分别监听span元素和button元素的点击, 在代码中实现页面跳转的功能**



<span @click=“homeSpanClick”>商品
<button @click=“btnClick”>信息


**使用push的特点是压入一个新的页面,那么在用户点击返回时,上一个页面还可以回退,但是如果我们希望当前页面是没有历史记录的,那么可以使用replace**:




**push中也可以传入一个对象, 对象的写法就可以通过query属性传递参数**



function homeSpanClick() {
router.push({
path: “/home/product”,
// 通过query传递参数
query: {
name: “chenyq”,
age: 18
}
})
}


**在界面中通过 $route.query 来获取参数**



{{ $route.query.name }} - {{ $route.query.age }}




---


**页面的前进后退**


**router的go方法**



// 导入函数useRouter
import { useRouter } from “vue-router”

// 通过函数useRouter拿到路由对象
const router = useRouter()

function goClick() {
// 向前移动一条记录
router.go(1)

// 返回一条记录
// router.go(-1)

/// 向前三条记录
// router.go(3)

// 如果没有name多条记录, 静默失败
// router.go(100)
// router.go(-100)
}


**router也有back**:



> 
> 通过调用 history.back() 回溯历史。相当于 router.go(-1);
> 
> 
> 



// 导入函数useRouter
import { useRouter } from “vue-router”

// 通过函数useRouter拿到路由对象
const router = useRouter()

function btnClick() {
router.back()
}


**router也有forward**:



> 
> 通过调用 history.forward() 在历史中前进。相当于 router.go(1);
> 
> 
> 



// 导入函数useRouter
import { useRouter } from “vue-router”

// 通过函数useRouter拿到路由对象
const router = useRouter()

function btnClick() {
router.forward()
}


### 动态添加路由


**某些情况下我们可能需要动态的来添加路由**:



> 
> 比如有一个后台管理系统, 我们需要根据用户不同的权限,注册不同的路由, 来显示符合用户权限的操作菜单;
> 
> 
> 这个时候我们可以使用一个方法 `addRoute`;
> 
> 
> 


**例如我们定义一个变量isAdmin用于判断用户是否是管理员 (真实开发这个用于判断的变量是来自网络请求的)**



> 
> 如果isAdmin为true, 那么说明是管理员, 就为管理员注册路由可以进入管理员界面
> 
> 
> 如果不是管理员, 那么就不会注册管理员界面的路由, 没有注册路由管理员界面就不会展示出来
> 
> 
> 



// 定义一个变量用于判断是否是管理员
let admine = false

if (admine) {
// 使用addRoute方法添加一级路由
router.addRoute({
path: “/admin”,
component: () => import(“…/views/Admin.vue”)
})
}


**上面是动态添加了一个一级路由, 那么能不能动态添加二级路由呢? 答案是肯定的**



// 定义一个变量用于判断是否是管理员
let admine = true

if (admine) {
// 动态添加二级路由, 第一个参数, 父路由的name值
router.addRoute(“home”, {
path: “vip”,
component: () => import(“…/views/HomeVip.vue”)
})
}




---


**动态管理路由的其他方法(了解)**


**删除路由有以下三种方式**:



> 
> 方式一:添加一个name相同的路由, 由于name是唯一的, 所以新添加的路由会把原来的路由覆盖掉;
> 
> 
> 方式二:通过`removeRoute(name值)`的方法,传入路由的名称;
> 
> 
> 方式三:通过addRoute方法的返回值回调;
> 
> 
> 



// 方式一
router.addRoute({ name: “about”, path: “/about”, component: About })
// 由于name相同, 新添加的会覆盖掉之前的路由
router.addRoute({ name: “about”, path: “/home”, component: Home })



// 方式二
router.addRoute({ name: “about”, path: “/about”, component: About })
// 通过removeRoute方法删除
router.removeRoute(“about”)



// 方式三
const remove = router.addRoute({ path: “/about”, component: About })
// 调用addRoute方法会有一个返回值, 调用返回值可以删除路由
remove()


**路由的其他方法补充**:



> 
> `router.hasRoute(name值)`:检查路由是否存在。
> 
> 
> 



console.log(router.hasRoute(“home”)) // true



> 
> `router.getRoutes()`:获取一个包含所有路由记录的数组。
> 
> 
> 



console.log(router.getRoutes())




---


### 路由导航守卫


#### 🍚beforeEach守卫函数



> 
> **在开发中我们使用最多的就是beforeEach守卫函数**
> 
> 
> 


**vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航, 那么什么是导航守卫呢**?



> 
> 在home页面跳转到about页面的这个过程, 我们称之为导航
> 
> 
> 在跳转这个过程的中间环节, 我们称之为导航守卫, 我们可以在这个环节对跳转进行拦截, 进行逻辑判断
> 
> 
> 


**全局的前置守卫beforeEach是在导航触发时会被回调的**:


**beforeEach传入一个函数, 传入的函数都会被回调, 且传入的函数有两个参数**:



> 
> `to`:即将进入的路由Route对象;
> 
> 
> `from`:即将离开的路由Route对象;
> 
> 
> 


**beforeEach有返回值**:



> 
> 返回false:取消当前导航;
> 
> 
> 不返回或者undefined:进行默认导航;
> 
> 
> 明确返回一个路由地址, 页面会跳转到返回的地址上去:
> 
> 
> * 可以是一个string类型的路径;
> * 可以是一个对象,对象中包含path、query、params等信息;
> 
> 
> 


**可选的第三个参数:next(不推荐使用)**



> 
> 在Vue2中我们是通过next函数来决定如何进行跳转的;
> 
> 
> 但是在Vue3中我们是通过返回值来控制的,不再推荐使用next函数,这是因为开发中很容易调用多次next;
> 
> 
> 


**比如我们完成如下一个功能**:



> 
> **现在我们有一个订单页面: 在订单页面我们主要实现两个逻辑**:
> 
> 
> 1. 判断用户是否登录
> 2. 根据逻辑进行不同的处理
> 
> 
> 用户已经登录, 进入订单页面
> 
> 
> 用户没有登录, 进入登录页面, 等到用户登录成功, 进入首页(或者订单页)
> 
> 
> 


**路由配置中的逻辑**:



// 路由导航守卫
router.beforeEach((to, from) => {
const token = localStorage.getItem(“token”)
// 判断用户是否登录, 是否去order页面
if (!token && to.path === “/order”) {
return “/login”
}
})


**order中的登录逻辑**



import { useRouter } from “vue-router”

const router = useRouter()

function loginClick() {
// 模拟向服务器发生请求, 服务器会返回token
localStorage.setItem(“token”, “chenyq”)
// 登录成功跳转会order页面
router.push(“/order”)
}




---


#### 🍚其他导航守卫(了解)


**Vue还提供了很多的其他守卫函数,目的都是在某一个时刻给予我们回调,让我们可以更好的控制程序的流程或者功能**:[文档链接](https://bbs.csdn.net/topics/618166371):https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html


**我们一起来看一下官方给出的完整的导航解析流程**:


1. 导航被触发。
2. 在失活的组件里调用 beforeRouteLeave 守卫。



> 
> 也就是说在我们离开的组件调用
> 
> 
> 


3. 调用全局的 beforeEach 守卫。
4. 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。



> 
> 比如/user/123 -> /user/321, 类似这种才会调用beforeRouteUpdate
> 
> 
> 




### 最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。

* **[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

  ![](https://img-blog.csdnimg.cn/img_convert/64ce8432d0f753e43f93972ad19fcd72.png)


![](https://img-blog.csdnimg.cn/img_convert/d508b1ae6a5e7d5e7d5daf668e9eccea.png)



})

order中的登录逻辑

import { useRouter } from "vue-router"

const router = useRouter()

function loginClick() {
  // 模拟向服务器发生请求, 服务器会返回token
  localStorage.setItem("token", "chenyq")
  // 登录成功跳转会order页面
  router.push("/order")
}


🍚其他导航守卫(了解)

Vue还提供了很多的其他守卫函数,目的都是在某一个时刻给予我们回调,让我们可以更好的控制程序的流程或者功能文档链接:https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html

我们一起来看一下官方给出的完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。

也就是说在我们离开的组件调用

  1. 调用全局的 beforeEach 守卫。
  2. 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。

比如/user/123 -> /user/321, 类似这种才会调用beforeRouteUpdate

最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值