程序猿之Vue - Day06 - Vue Router 声明式导航、编程式跳转、路由参数传参、组件缓存进阶

一、声明式导航-导航链接

1.需求

实现导航高亮效果

如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!!

✅ 理论理解:

<router-link> 是 Vue Router 提供的路由跳转组件,替代 <a> 标签使用。它不仅能跳转,而且可以自动添加“高亮”类名,避免手动维护当前页面样式。

🚀 大厂实战理解:

字节跳动中后台系统组件封装 BaseLink 组件统一代理 <router-link>,增强跳转监控、埋点打点与权限判断能力。

 

2.解决方案

vue-router 提供了一个全局组件 router-link (取代 a 标签)

  • 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #

  • 能高亮,默认就会提供高亮类名,可以直接设置高亮样式

语法: <router-link to="path的值">发现音乐</router-link>

  <div>
    <div class="footer_wrap">
      <router-link to="/find">发现音乐</router-link>
      <router-link to="/my">我的音乐</router-link>
      <router-link to="/friend">朋友</router-link>
    </div>
    <div class="top">
      <!-- 路由出口 → 匹配的组件所展示的位置 -->
      <router-view></router-view>
    </div>
  </div>

3.通过router-link自带的两个样式进行高亮

使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-activerouter-link-active

我们可以给任意一个class属性添加高亮样式即可实现功能

4.总结

  • router-link是什么?

  • router-link怎么用?

  • router-link的好处是什么?

二、声明式导航-两个类名

当我们使用<router-link></router-link>跳转时,自动给当前导航加了两个类名

1.router-link-active

模糊匹配(用的多)

to="/my" 可以匹配 /my /my/a /my/b ....

只要是以/my开头的路径 都可以和 to="/my"匹配到

2.router-link-exact-active

精确匹配

to="/my" 仅可以匹配 /my

3.在地址栏中输入二级路由查看类名的添加

4.总结

  • router-link 会自动给当前导航添加两个类名,有什么区别呢?

✅ 理论理解:

router-link-active 是模糊匹配的类名;router-link-exact-active 是精确匹配。Vue 会自动根据路径匹配结果添加它们。

🚀 大厂实战理解:

阿里云统一使用 router-link-exact-active 控制主菜单激活项;子菜单则使用自定义类名与 Vuex 联动控制,增强可维护性。

三、声明式导航-自定义类名(了解)

1.问题

router-link的两个高亮类名 太长了,我们希望能定制怎么办

2.解决方案

我们可以在创建路由对象时,额外配置两个配置项即可。 linkActiveClasslinkExactActiveClass

const router = new VueRouter({
  routes: [...],
  linkActiveClass: "类名1",
  linkExactActiveClass: "类名2"
})

3.代码演示

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    ...
  ], 
  linkActiveClass: 'active', // 配置模糊匹配的类名
  linkExactActiveClass: 'exact-active' // 配置精确匹配的类名
})

4.总结

如何自定义router-link的两个高亮类名

✅ 理论理解:

可以在 VueRouter 实例中配置 linkActiveClasslinkExactActiveClass 来覆盖默认类名,使样式更贴合业务需求。

🚀 大厂实战理解:

腾讯课堂统一配置高亮类为 nav-active,并在组件中通过 SCSS 全局样式预定义好交互样式,方便切换主题色。

四、声明式导航-查询参数传参

1.目标

在跳转路由时,进行传参

 

比如:现在我们在搜索页点击了热门搜索链接,跳转到详情页,需要把点击的内容带到详情页,改怎么办呢?

2.跳转传参

我们可以通过两种方式,在跳转的时候把所需要的参数传到其他页面中

  • 查询参数传参

  • 动态路由传参

3.查询参数传参

  • 如何传参?

    <router-link to="/path?参数名=值"></router-link>

  • 如何接受参数

    固定用法:$router.query.参数名

4.代码演示

App.vue

<template>
  <div id="app">
    <div class="link">
      <router-link to="/home">首页</router-link>
      <router-link to="/search">搜索页</router-link>
    </div>
​
    <router-view></router-view>
  </div>
</template>
​
<script>
export default {};
</script>
​
<style scoped>
.link {
  height: 50px;
  line-height: 50px;
  background-color: #495150;
  display: flex;
  margin: -8px -8px 0 -8px;
  margin-bottom: 50px;
}
.link a {
  display: block;
  text-decoration: none;
  background-color: #ad2a26;
  width: 100px;
  text-align: center;
  margin-right: 5px;
  color: #fff;
  border-radius: 5px;
}
</style>

Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text">
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="">黑马程序员</router-link>
      <router-link to="">前端培训</router-link>
      <router-link to="">如何成为前端大牛</router-link>
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'FindMusic'
}
</script>
​
<style>
.logo-box {
  height: 150px;
  background: url('@/assets/logo.jpeg') no-repeat center;
}
.search-box {
  display: flex;
  justify-content: center;
}
.search-box input {
  width: 400px;
  height: 30px;
  line-height: 30px;
  border: 2px solid #c4c7ce;
  border-radius: 4px 0 0 4px;
  outline: none;
}
.search-box input:focus {
  border: 2px solid #ad2a26;
}
.search-box button {
  width: 100px;
  height: 36px;
  border: none;
  background-color: #ad2a26;
  color: #fff;
  position: relative;
  left: -2px;
  border-radius: 0 4px 4px 0;
}
.hot-link {
  width: 508px;
  height: 60px;
  line-height: 60px;
  margin: 0 auto;
}
.hot-link a {
  margin: 0 5px;
}
</style>

Search.vue

<template>
  <div class="search">
    <p>搜索关键字: 黑马程序员</p>
    <p>搜索结果: </p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>
​
<script>
export default {
  name: 'MyFriend',
  created () {
    // 在created中,获取路由参数
  }
}
</script>
​
<style>
.search {
  width: 400px;
  height: 240px;
  padding: 0 20px;
  margin: 0 auto;
  border: 2px solid #c4c7ce;
  border-radius: 5px;
}
</style>

router/index.js

import Home from '@/views/Home'
import Search from '@/views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化
​
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/search', component: Search }
  ]
})
​
export default router

main.js

...
import router from './router/index'
...
new Vue({
  render: h => h(App),
  router
}).$mount('#app')
✅ 理论理解:

通过 <router-link :to="{}"> 的对象写法,可以使用 query 属性传参,接收方式为 $route.query.xxx

🚀 大厂实战理解:

美团外卖搜索模块中,热门关键词通过 query 传参到详情页,页面可直接还原上次搜索条件,支持深度链接跳转。

五、声明式导航-动态路由传参

1.动态路由传参方式

  • 配置动态路由

    动态路由后面的参数可以随便起名,但要有语义

    const router = new VueRouter({
      routes: [
        ...,
        { 
          path: '/search/:words', 
          component: Search 
        }
      ]
    })
  • 配置导航链接

    to="/path/参数值"

  • 对应页面组件接受参数

    $route.params.参数名

    params后面的参数名要和动态路由配置的参数保持一致

2.查询参数传参 VS 动态路由传参

  1. 查询参数传参 (比较适合传多个参数)

    1. 跳转:to="/path?参数名=值&参数名2=值"

    2. 获取:$route.query.参数名

  2. 动态路由传参 (优雅简洁,传单个参数比较方便)

    1. 配置动态路由:path: "/path/:参数名"

    2. 跳转:to="/path/参数值"

    3. 获取:$route.params.参数名

    注意:动态路由也可以传多个参数,但一般只传一个

3.总结

声明式导航跳转时, 有几种方式传值给路由页面?

  • 查询参数传参(多个参数)

  • 动态路由传参(一个参数,优雅简洁)

✅ 理论理解:

动态路由通过 path: '/xxx/:id' 配置参数,跳转时传入路径变量,使用 $route.params.xxx 接收。

🚀 大厂实战理解:

百度招聘系统中,每条职位详情页都通过动态路由传参,URL 美观并可直接复制分享给他人。

六、动态路由参数的可选符(了解)

1.问题

配了路由 path:"/search/:words" 为什么按下面步骤操作,会未匹配到组件,显示空白?

 

2.原因

/search/:words 表示,必须要传参数。如果不传参数,也希望匹配,可以加个可选符"?"

const router = new VueRouter({
  routes: [
    ...
    { path: '/search/:words?', component: Search }
  ]
})
✅ 理论理解:

/search/:word? 中的 ? 表示该参数可选,避免用户直接访问 /search 时不匹配路由导致白屏。

🚀 大厂实战理解:

字节前台系统中多个模块通过可选参数控制首屏展示行为,例如首页是否带搜索结果状态,由路径参数控制。

 

七、Vue路由-重定向

1.问题

网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白

 

2.解决方案

重定向 → 匹配 / 后, 强制跳转 /home 路径

3.语法

{ path: 匹配路径, redirect: 重定向到的路径 },
比如:
{ path:'/' ,redirect:'/home' }

4.代码演示

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/home'},
     ...
  ]
})
✅ 理论理解:

通过配置 redirect 属性可将某路径自动跳转至目标路径,常用于 / 路由重定向至 /home

🚀 大厂实战理解:

NVIDIA 控制面板中 / 自动重定向至默认工作空间页,同时根据不同用户权限进行个性化跳转。

八、Vue路由-404

1.作用

当路径找不到匹配时,给个提示页面

2.位置

404的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面

3.语法

path: "*" (任意路径) – 前面不匹配就命中最后这个

import NotFind from '@/views/NotFind'
​
const router = new VueRouter({
  routes: [
    ...
    { path: '*', component: NotFind } //最后一个
  ]
})

4.代码示例

NotFound.vue

<template>
  <div>
    <h1>404 Not Found</h1>
  </div>
</template>
​
<script>
export default {
​
}
</script>
​
<style>
​
</style>

router/index.js

...
import NotFound from '@/views/NotFound'
...
​
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
     ...
    { path: '*', component: NotFound }
  ]
})
​
export default router
✅ 理论理解:

使用通配路径 * 捕获未命中的路由并展示 404 页面,需放在所有路由规则最后。

🚀 大厂实战理解:

Google Cloud 前端统一兜底路径转入 404 页,并在控制台中自动上报用户访问错误路径,辅助运维排查。

九、Vue路由-模式设置

1.问题

路由的路径看起来不自然, 有#,能否切成真正路径形式?

2.语法

const router = new VueRouter({
    mode:'histroy', //默认是hash
    routes:[]
})
✅ 理论理解:

Vue Router 默认是 Hash 模式,路径中含 #;如需更干净的路径(如 /home),则需配置为 History 模式,并确保后端配置正确的重定向规则。

🚀 大厂实战理解:

OpenAI Playground 的路由全部采用 History 模式,配合 Cloudflare Edge 配置进行智能 fallback 支持。

十、编程式导航-两种路由跳转方式

1.问题

点击按钮跳转如何实现?

 

2.方案

编程式导航:用JS代码来进行跳转

3.语法

两种语法:

  • path 路径跳转 (简易方便)

  • name 命名路由跳转 (适合 path 路径长的场景)

4.path路径跳转语法

特点:简易方便

//简单写法
this.$router.push('路由路径')

//完整写法
this.$router.push({
  path: '路由路径'
})

5.代码演示 path跳转方式

6.name命名路由跳转

特点:适合 path 路径长的场景

语法:

  • 路由规则,必须配置name配置项

    { name: '路由名', path: '/path/xxx', component: XXX },

  • 通过name来进行跳转

    this.$router.push({
      name: '路由名'
    })

7.代码演示通过name命名路由跳转

8.总结

编程式导航有几种跳转方式?

✅ 理论理解:

通过 JS 代码跳转页面的方式称为编程式导航。支持两种语法:this.$router.push('path')this.$router.push({ name: 'xxx' })

🚀 大厂实战理解:

阿里钉钉小程序使用 name 模式统一跳转逻辑,便于维护与权限控制。

十一、编程式导航-path路径跳转传参

1.问题

点击搜索按钮,跳转需要把文本框中输入的内容传到下一个页面如何实现?

 

2.两种传参方式

1.查询参数

2.动态路由传参

3.传参

两种跳转方式,对于两种传参方式都支持:

① path 路径跳转传参

② name 命名路由跳转传参

4.path路径跳转传参(query传参)

//简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
//完整写法
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

接受参数的方式依然是:$route.query.参数名

5.path路径跳转传参(动态路由传参)

//简单写法
this.$router.push('/路径/参数值')
//完整写法
this.$router.push({
  path: '/路径/参数值'
})

接受参数的方式依然是:$route.params.参数值

注意:path不能配合params使用

✅ 理论理解:

使用 this.$router.push({ path: '/xxx', query: { k: v } }) 进行查询参数传递,或直接拼接 /xxx/value 进行动态路由传递。

🚀 大厂实战理解:

百度教育平台中,跳转课程页时用 query 携带筛选条件;跳转详情页时用 path 动态参数携带课程 ID。

十二、编程式导航-name命名路由传参

1.name 命名路由跳转传参 (query传参)

this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

2.name 命名路由跳转传参 (动态路由传参)

this.$router.push({
  name: '路由名字',
  params: {
    参数名: '参数值',
  }
})

3.总结

编程式导航,如何跳转传参?

1.path路径跳转

  • query传参

    this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
    this.$router.push({
      path: '/路径',
      query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
      }
    })

  • 动态路由传参

    this.$router.push('/路径/参数值')
    this.$router.push({
      path: '/路径/参数值'
    })

2.name命名路由跳转

  • query传参

    this.$router.push({
      name: '路由名字',
      query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
      }
    })

  • 动态路由传参 (需要配动态路由)

    this.$router.push({
      name: '路由名字',
      params: {
        参数名: '参数值',
      }
    })
    ✅ 理论理解:

    通过命名路由方式传参,可以使用 queryparams,其中 params 需与 :xxx 路由参数一一对应。

    🚀 大厂实战理解:

    腾讯 TIM Web 端采用命名路由 + 动态参数组合实现聊天会话跳转,避免硬编码路径带来的维护风险。

十三、面经基础版-案例效果分析

1.面经效果演示

2.功能分析

  • 通过演示效果发现,主要的功能页面有两个,一个是列表页,一个是详情页,并且在列表页点击时可以跳转到详情页

  • 底部导航可以来回切换,并且切换时,只有上面的主题内容在动态渲染

 

3.实现思路分析:配置路由+功能实现

1.配置路由

  • 首页和面经详情页,两个一级路由

  • 首页内嵌套4个可切换的页面(嵌套二级路由)

2.实现功能

  • 首页请求渲染

  • 跳转传参 到 详情页,详情页动态渲染

  • 组件缓存,性能优化

 

十四、面经基础版-一级路由配置

1.把文档中准备的素材拷贝到项目中

2.针对router/index.js文件 进行一级路由配置

...
import Layout from '@/views/Layout.vue'
import ArticleDetail from '@/views/ArticleDetail.vue'
...


const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout
    },
    {
      path: '/detail',
      component: ArticleDetail
    }
  ]
})

十五、面经基础版-二级路由配置

二级路由也叫嵌套路由,当然也可以嵌套三级、四级...

1.使用场景

当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由

2.语法

  • 在一级路由下,配置children属性即可

  • 配置二级路由的出口

1.在一级路由下,配置children属性

注意:一级的路由path 需要加 / 二级路由的path不需要加 /

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout,
      children:[
        //children中的配置项 跟一级路由中的配置项一模一样 
        {path:'xxxx',component:xxxx.vue},
        {path:'xxxx',component:xxxx.vue},
      ]
    }
  ]
})

技巧:二级路由应该配置到哪个一级路由下呢?

这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边

2.配置二级路由的出口 <router-view></router-view>

注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件

Layout.vue

<template>
  <div class="h5-wrapper">
    <div class="content">
      <router-view></router-view>
    </div>
  ....
  </div>
</template>

3.代码实现

router/index.js

...
import Article from '@/views/Article.vue'
import Collect from '@/views/Collect.vue'
import Like from '@/views/Like.vue'
import User from '@/views/User.vue'
...

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout,
      redirect: '/article',
      children:[
        {
          path:'/article',
          component:Article
        },
        {
          path:'/collect',
          component:Collect
        },
        {
          path:'/like',
          component:Like
        },
        {
          path:'/user',
          component:User
        }
      ]
    },
    ....
  ]
})

Layout.vue

<template>
  <div class="h5-wrapper">
    <div class="content">
      <!-- 内容部分 -->
      <router-view></router-view>
    </div>
    <nav class="tabbar">
      <a href="#/article">面经</a>
      <a href="#/collect">收藏</a>
      <a href="#/like">喜欢</a>
      <a href="#/user">我的</a>
    </nav>
  </div>
</template>

十六、面经基础版-二级导航高亮

1.实现思路

  • 将a标签替换成 <router-link></router-link>组件,配置to属性,不用加 #

  • 结合高亮类名实现高亮效果 (推荐模糊匹配:router-link-active)

2.代码实现

Layout.vue

....
    <nav class="tabbar">
      <router-link to="/article">面经</router-link>
      <router-link to="/collect">收藏</router-link>
      <router-link to="/like">喜欢</router-link>
      <router-link to="/user">我的</router-link>
    </nav>

<style>
   a.router-link-active {
      color: orange;
    }
</style>

十七、面经基础版-首页请求渲染

1.步骤分析

1.安装axios

2.看接口文档,确认请求方式,请求地址,请求参数

3.created中发送请求,获取数据,存储到data中

4.页面动态渲染

2.代码实现

1.安装axios

yarn add axios npm i axios

2.接口文档

请求地址: https://mock.boxuegu.com/mock/3083/articles
请求方式: get

3.created中发送请求,获取数据,存储到data中

 data() {
    return {
      articelList: [],
    }
  },
  async created() {
    const {  data: { result: { rows } }} = await axios.get('https://mock.boxuegu.com/mock/3083/articles')
    this.articelList = rows
  },

4.页面动态渲染

<template>
  <div class="article-page">
    <div class="article-item" v-for="item in articelList" :key="item.id">
      <div class="head">
        <img :src="item.creatorAvatar" alt="" />
        <div class="con">
          <p class="title">{{ item.stem }}</p>
          <p class="other">{{ item.creatorName }} | {{ item.createdAt }}</p>
        </div>
      </div>
      <div class="body">
        {{item.content}}
      </div>
      <div class="foot">点赞 {{item.likeCount}} | 浏览 {{item.views}}</div>
    </div>
  </div>
</template>

十八、面经基础版-查询参数传参

1.说明

跳转详情页需要把当前点击的文章id传给详情页,获取数据

  • 查询参数传参 this.$router.push('/detail?参数1=参数值&参数2=参数值')

  • 动态路由传参 先改造路由 在传参 this.$router.push('/detail/参数值')

2.查询参数传参实现

Article.vue

<template>
  <div class="article-page">
    <div class="article-item" 
      v-for="item in articelList" :key="item.id" 
      @click="$router.push(`/detail?id=${item.id}`)">
     ...
    </div>
  </div>
</template>

ArticleDetail.vue

  created(){
    console.log(this.$route.query.id)
  }

十九、面经基础版-动态路由传参

1.实现步骤

  • 改造路由

  • 动态传参

  • 在详情页获取参数

2.代码实现

改造路由

router/index.js

...
  {
      path: '/detail/:id',
      component: ArticleDetail
  }

Article.vue

<div class="article-item" 
     v-for="item in articelList" :key="item.id" 
     @click="$router.push(`/detail/${item.id}`)">
       ....
 </div>

ArticleDetail.vue

  created(){
    console.log(this.$route.params.id)
  }

3.额外优化功能点-点击回退跳转到上一页

ArticleDetail.vue

<template>
  <div class="article-detail-page">
    <nav class="nav"><span class="back" @click="$router.back()">&lt;</span> 面经详情</nav>
     ....
  </div>
</template>

二十、面经基础版-详情页渲染

1.实现步骤分析

  • 导入axios

  • 查看接口文档

  • 在created中发送请求

  • 页面动态渲染

2.代码实现

接口文档

 请求地址: https://mock.boxuegu.com/mock/3083/articles/:id
 请求方式: get

在created中发送请求

data() {
    return {
      articleDetail:{}
    }
  },
  async created() {
    const id = this.$route.params.id
    const {data:{result}} = await axios.get(
      `https://mock.boxuegu.com/mock/3083/articles/${id}`
    )
    this.articleDetail = result
  },

页面动态渲染

<template>
  <div class="article-detail-page">
    <nav class="nav">
      <span class="back" @click="$router.back()">&lt;</span> 面经详情
    </nav>
    <header class="header">
      <h1>{{articleDetail.stem}}</h1>
      <p>{{articleDetail.createAt}} | {{articleDetail.views}} 浏览量 | {{articleDetail.likeCount}} 点赞数</p>
      <p>
        <img
          :src="articleDetail.creatorAvatar"
          alt=""
        />
        <span>{{articleDetail.creatorName}}</span>
      </p>
    </header>
    <main class="body">
      {{articleDetail.content}}
    </main>
  </div>
</template>

二十一、面经基础版-缓存组件

1.问题

从面经列表 点到 详情页,又点返回,数据重新加载了 → 希望回到原来的位置

 

2.原因

当路由被跳转后,原来所看到的组件就被销毁了(会执行组件内的beforeDestroy和destroyed生命周期钩子),重新返回后组件又被重新创建了(会执行组件内的beforeCreate,created,beforeMount,Mounted生命周期钩子),所以数据被加载了

3.解决方案

利用keep-alive把原来的组件给缓存下来

4.什么是keep-alive

keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。

优点:

在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,

减少加载时间及性能消耗,提高用户体验性。

App.vue

<template>
  <div class="h5-wrapper">
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

问题:

缓存了所有被切换的组件

5.keep-alive的三个属性

① include : 组件名数组,只有匹配的组件会被缓存

② exclude : 组件名数组,任何匹配的组件都不会被缓存

③ max : 最多可以缓存多少组件实例

App.vue

<template>
  <div class="h5-wrapper">
    <keep-alive :include="['LayoutPage']">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

6.额外的两个生命周期钩子

keep-alive的使用会触发两个生命周期函数

activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发

deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发

组件缓存后不会执行组件的created, mounted, destroyed 等钩子了

所以其提供了actived 和deactived钩子,帮我们实现业务需求。

7.总结

1.keep-alive是什么

2.keep-alive的优点

3.keep-alive的三个属性 (了解)

4.keep-alive的使用会触发两个生命周期函数(了解)

二十二、VueCli 自定义创建项目

1.安装脚手架 (已安装)

npm i @vue/cli -g

2.创建项目

vue create hm-exp-mobile
  • 选项

Vue CLI v5.0.8
? Please pick a preset:
  Default ([Vue 3] babel, eslint)
  Default ([Vue 2] babel, eslint)
> Manually select features     选自定义
  • 手动选择功能

 

  • 选择vue的版本

  3.x
> 2.x
  • 是否使用history模式

 

  • 选择css预处理

 

  • 选择eslint的风格 (eslint 代码规范的检验工具,检验代码是否符合规范)

  • 比如:const age = 18; => 报错!多加了分号!后面有工具,一保存,全部格式化成最规范的样子

 

  • 选择校验的时机 (直接回车)

 

  • 选择配置文件的生成方式 (直接回车)

 

  • 是否保存预设,下次直接使用? => 不保存,输入 N

 

  • 等待安装,项目初始化完成

 

  • 启动项目

npm run serve

二十三、ESlint代码规范及手动修复

代码规范:一套写代码的约定规则。例如:赋值符号的左右是否需要空格?一句结束是否是要加;?...

没有规矩不成方圆

ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则。

1.JavaScript Standard Style 规范说明

建议把:JavaScript Standard Style 看一遍,然后在写的时候, 遇到错误就查询解决。

下面是这份规则中的一小部分:

  • 字符串使用单引号 – 需要转义的地方除外

  • 无分号没什么不好。不骗你!

  • 关键字后加空格 if (condition) { ... }

  • 函数名后加空格 function name (arg) { ... }

  • 坚持使用全等 === 摒弃 == 一但在需要检查 null || undefined 时可以使用 obj == null

  • ......

2.代码规范错误

如果你的代码不符合standard的要求,eslint会跳出来刀子嘴,豆腐心地提示你。

下面我们在main.js中随意做一些改动:添加一些空行,空格。

import Vue from 'vue'
import App from './App.vue'

import './styles/index.less'
import router from './router'
Vue.config.productionTip = false

new Vue ( {
  render: h => h(App),
  router
}).$mount('#app')

按下保存代码之后:

你将会看在控制台中输出如下错误:

 

eslint 是来帮助你的。心态要好,有错,就改。

3.手动修正

根据错误提示来一项一项手动修正。

如果你不认识命令行中的语法报错是什么意思,你可以根据错误代码(func-call-spacing, space-in-parens,.....)去 ESLint 规则列表中查找其具体含义。

打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

二十四、通过eslint插件来实现自动修正

  1. eslint会自动高亮错误显示

  2. 通过配置,eslint会自动帮助我们修复错误

  • 如何安装

 

  • 如何配置

// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {
    "source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false
  • 注意:eslint的配置文件必须在根目录下,这个插件才能才能生效。打开项目必须以根目录打开,一次打开一个项目

  • 注意:使用了eslint校验之后,把vscode带的那些格式化工具全禁用了 Beatify

settings.json 参考

{
    "window.zoomLevel": 2,
    "workbench.iconTheme": "vscode-icons",
    "editor.tabSize": 2,
    "emmet.triggerExpansionOnTab": true,
    // 当保存的时候,eslint自动帮我们修复错误
    "editor.codeActionsOnSave": {
        "source.fixAll": true
    },
    // 保存代码,不自动格式化
    "editor.formatOnSave": false
}

好的,以下是《Day06 - Vue Router》配套的【大厂面试题】,每道题均紧扣你 Day06 的原始知识点结构,并包含真实面试高频提问的表述风格,可直接嵌入对应小节下方作为复习、查漏补缺使用。


🧠 面试题 - Vue Router 路由跳转、参数传参与组件缓存


一、router-link 是如何实现导航跳转的?和原生 a 标签的差异是什么?

答:

  • <router-link> 本质还是 <a>,但它不会引起浏览器刷新;

  • Vue Router 内部通过调用 history.pushState() 改变 URL 并维护组件状态;

  • 同时,它会根据当前路由路径,自动添加 router-link-activerouter-link-exact-active 类名。


二、router-link 会添加两个类名,解释它们的区别及使用场景?

答:

类名说明使用场景
router-link-active模糊匹配路径多级路径导航,如 tab 切换
router-link-exact-active精确匹配完整路径精准控制菜单项激活状态

三、什么场景下需要自定义 router-link 的高亮类名?如何实现?

答:

  • 场景:当项目使用了统一的 CSS 命名规范(如 BEM、Tailwind)时,默认类名可能不适配;

  • 解决方案:通过 Vue Router 实例配置 linkActiveClasslinkExactActiveClass

const router = new VueRouter({
  linkActiveClass: 'my-active',
  linkExactActiveClass: 'my-exact',
  routes: [...]
})

四、在 <router-link> 中如何传递参数?有哪些方式?分别适用于什么场景?

答:

  1. Query 参数传参:

    <router-link :to="{ path: '/search', query: { key: 'vue' } }" />
    
    • 场景:搜索、多条件筛选

  2. 动态路由参数传参:

    <router-link :to="`/detail/${id}`" />
    
    • 场景:跳转详情页、传唯一标识 ID


五、动态路由与查询参数传参的区别?如何选择?

答:

比较点查询参数(query)动态路由参数(params)
URL 示例/search?word=vue/search/vue
路由配置不需要特别设置需要设置 :word
接收方式$route.query.word$route.params.word
场景推荐多参数、可选项多精准 ID 或资源标识

六、为什么 /search/:words 有时会无法匹配?如何解决?

答:

  • /search/:words 表示必须带参数;

  • 若路径为 /search,则无法匹配;

  • 解决:在参数后加 ? 表示可选,如 /search/:words?


七、Vue Router 中如何实现 404 页面?为什么要放最后?

答:

  • 使用通配路由 * 捕获未匹配路径,跳转至 404 组件;

  • 必须放在路由表最后,避免优先匹配拦截有效路径。

{ path: '*', component: NotFound }

八、Vue Router 中的 Hash 模式和 History 模式有什么区别?

答:

模式路径结构是否依赖后端配置SEO 是否友好
Hash 模式/#/home
History 模式/home是(需 rewrite)是(更真实)

九、什么是编程式导航?和声明式导航有什么区别?

答:

  • 编程式导航: 通过 JS 调用 this.$router.push(...) 跳转页面;

  • 声明式导航: 通过 <router-link> 写在模板中直接跳转;

  • 编程式适合逻辑控制跳转,如按钮点击、事件响应等场景。


十、Vue Router 中 name 路由跳转有什么好处?

答:

  • 避免硬编码路径,增强跳转的语义性与可维护性;

  • 在路由路径可能变化的场景下,name 路由更稳定:

this.$router.push({ name: 'DetailPage', params: { id: 123 } })

十一、动态参数能否与 query 一起使用?怎么组合?

答:

可以,二者互不冲突:

this.$router.push({
  name: 'DetailPage',
  params: { id: 123 },
  query: { ref: 'search' }
})

接收方式:

  • $route.params.id

  • $route.query.ref


十二、什么是 keep-alive?哪些生命周期在缓存组件中不会执行?

答:

  • keep-alive 是 Vue 内置组件,用于缓存被包裹的组件;

  • 缓存后组件不会重新销毁和挂载,因此不会触发:

    • created, mounted, destroyed

  • 替代钩子:

    • activated: 组件激活时调用

    • deactivated: 组件离开视图时调用


十三、keep-alive 如何指定只缓存某些组件?如何排除?

答:

<keep-alive :include="['ArticlePage']" :exclude="['LoginPage']">
  <router-view />
</keep-alive>

配合组件名或路由 meta.cache 控制更灵活。


十四、组件缓存后,如何实现“返回原位置”的体验优化?

答:

deactivated 中记录滚动位置,在 activated 中恢复:

data() {
  return { scrollY: 0 }
},
deactivated() {
  this.scrollY = document.documentElement.scrollTop
},
activated() {
  window.scrollTo(0, this.scrollY)
}


🏢 场景题 - Vue Router 组件跳转、参数传参、缓存优化实战场景


❶ 场景题:如何实现页面跳转时自动高亮左侧导航?(router-link 高亮类)

✅ 背景说明:

产品经理希望左侧菜单栏在不同页面跳转时自动高亮当前模块导航。

🚀 大厂真实案例:

阿里中台前端在多个微应用框架下采用统一封装的 BaseLink 组件,内嵌 <router-link> 并结合 router-link-active 控制选中样式,同时通过 activeMenu 进行导航项补高亮。

💡 场景追问:

如果某个页面路径很深,如 /user/edit/123,但菜单只配置了 /user,你会怎么高亮它?

✅ 回答建议:利用模糊匹配 router-link-active,或者在每个路由 meta 中增加 activeMenu 字段指向 /user,用于菜单联动高亮。


❷ 场景题:点击搜索关键词跳转详情页,同时页面能记住当前筛选条件

✅ 背景说明:

在搜索页点击“热门词”时,跳转到搜索详情页面,并希望记住此前筛选状态。

🚀 字节跳动真实场景:

字节小程序“抖店运营助手”中,点击热词后通过 query 参数传参跳转搜索页,搜索页通过 this.$route.query.keyword 拿到关键词,同时保留其他筛选条件。

💡 场景追问:

为什么不用动态路由传参?是否能做到刷新页面也保留条件?

✅ 回答建议:query 结构化更清晰,支持多参数传递;URL 能深链分享并持久化查询条件,刷新后依然保留。


❸ 场景题:详情页返回后,如何恢复原来的列表滚动位置?

✅ 背景说明:

点击某条文章进入详情页后,再返回列表页,希望能回到上次浏览的位置,而不是重新加载。

🚀 美团外卖 WebApp 实战:

美团 WebApp 使用 <keep-alive> 缓存列表页,deactivated 记录 scrollTop,activated 恢复:

activated () {
  window.scrollTo(0, this.savedScrollTop || 0)
}
💡 场景追问:

组件被缓存后 created 不会执行,数据不更新怎么办?

✅ 回答建议:结合 activated 中判断是否需要刷新,或设置路由 meta.cache = false 控制不缓存部分页面。


❹ 场景题:如何配置 SPA 项目的 404 页面?

✅ 背景说明:

用户访问了错误路径 /xyz,页面应显示友好的 404 提示页面。

🚀 百度 Apollo 前端方案:

使用 { path: '*', component: NotFound } 放在所有路由规则最后,404 页面中添加“返回首页”按钮 + 自动跳首页倒计时。

💡 场景追问:

若使用了 history 模式,为什么部署后访问 404 会报错?

✅ 回答建议:因为 history 模式下直接访问路径会请求后端资源,需服务端配置 rewrite:

location / {
  try_files $uri $uri/ /index.html;
}

❺ 场景题:登录后动态根据权限加载路由和菜单

✅ 背景说明:

用户登录后才加载菜单项,系统根据权限返回不同可访问页面。

🚀 腾讯云前端方案:

登录成功后,请求权限接口,拿到路由表数组,通过 router.addRoute() 动态挂载到主 layout 下,并设置 meta.permission = true 控制页面访问。

💡 场景追问:

刷新页面后会导致权限路由失效,如何解决?

✅ 回答建议:路由信息需持久化到 localStorage,再次进入时判断用户状态并重新 addRoute;或封装 NavigationGuard 全局判断。


❻ 场景题:点击一个按钮跳转路径 /path?id=xxx&type=yyy,你怎么实现?

✅ 背景说明:

前端需要将多个字段拼接为参数跳转另一个页面,并在目标页读取参数。

🚀 京东中台实战:

通过 this.$router.push({ path: '/path', query: { id, type } }) 实现参数拼接;目标页通过 this.$route.query 获取值,赋予组件初始状态。

💡 场景追问:

当参数过多或层级较深时,你如何做参数管理?

✅ 回答建议:可封装 query 序列化/反序列化方法,避免手写拼接;或建立 route 路径构造函数 buildSearchRoute({ ...params })


❼ 场景题:点击不同课程进入详情页(路径为 /course/:id),如何使用动态路由加载数据?

✅ 背景说明:

课程详情页路径形如 /course/123,需要根据 id 请求并展示课程内容。

🚀 网易云课堂实战:

配置动态路由 /course/:id,组件中通过 this.$route.params.id 获取 ID,发送异步请求渲染页面。

💡 场景追问:

如果用户手动修改 URL /course/456 会怎样?你要如何处理异常?

✅ 回答建议:应在 created 请求中加入错误处理,如 404 fallback;若课程不存在则跳转提示页或回退上一级页面。


❽ 场景题:如何根据路由状态控制多个 tab 页的缓存与激活?

✅ 背景说明:

多个标签页如“面经”、“收藏”、“我的”等页面,需要切换时缓存组件状态,但不希望缓存详情页。

🚀 字节跳动面试宝实战:

使用 keep-alive :include="['Article', 'Collect', 'User']" 精准缓存路由组件,通过组件名筛选。

每个二级页面组件设置:

export default {
  name: 'Collect', // 必须与 keep-alive 中一致
  ...
}
💡 场景追问:

组件频繁缓存会不会内存占用高?如何控制?

✅ 回答建议:可结合 keep-alive 的 max 属性控制缓存数量,或使用 meta.cache = true/false 动态决定缓存策略。


✅ 总结建议

场景关键词涉及知识点
搜索跳转/恢复状态query 传参 + keep-alive
多级导航高亮router-link-active + meta
登录后动态路由加载router.addRoute + 权限系统
404 错误处理通配路由 + history 模式处理
参数跳转与获取query vs params
组件缓存与滚动还原activated + deactivated

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值