VueRouter

220 阅读4分钟

1. route 和 router 的区别

  • route:当前路由对象

  • $route:用来获取路由信息【路径、query、params 等等】

  • router:VueRouter 的实例对象

  • $router:用来操作路由,如进行编程式导航跳转【push|replace】

    • 她包含了所有的路由、包括路由的跳转方法、钩子函数、子对象(history)

2. vue-router 怎么重定向页面

在路由中配置 redirect 属性

3. vue-router 怎么重定向

redirect 动态的话,在回调里面写逻辑判断

4. vue-router 怎么配置 404 页面

配置 path: '*' ,并且放到最后面。因为路由是从上往下执行的

5. vue-router 切换路由,需要保存草稿的功能,怎么实现

在 beforeRouteLeave 写逻辑

6. vue-router 路由有几种模式?区别

hash 模式

  • url 路径会出现 # 号字符

  • hash 值不包括在 Http 请求中,它是交给前端路由处理的。所以改变 hash 值不会刷新页面,也不会向服务器发起请求,所以这也是单页面应用的必备

  • hash 值的改变会触发 hashchange 事件

  • 当我们进行刷新操作,或者直接输入浏览器地址时

    • hash 路由会加载到地址栏对应的页面
    • history 路由一般会 404 报错,(因为刷新是网络请求,没有后端准备时,会报错)

history 模式

  • history 运用了浏览器的历史记录栈,提供了对历史记录进行修改的功能

  • history 模式需要后台配置支持。

    • 当我们刷新,或者输入浏览器地址的时候,就一定要向服务器发起请求
    • 但是,如果这个目标不在服务器上,就会返回 404
  • hash 路由支持低版本浏览器,而 history 路由是 HTML5 新增的 API

7. 如果 vue-rouer 使用 history 模式,部署时需要注意什么

服务器的 404 页面需要重定向到 index.html

8. vue-router 有哪几种导航钩子(导航守卫)

  • 钩子函数种类有:全局守卫、路由守卫、组件守卫
  • 全局导航钩子:beforeEach(全局前置守卫)、beforeResolve(全局解析守卫)、afterEach(全局后置钩子)
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

9. vue-router 完整的导航解析流程是什么

# 关于Vue-Router4路由导航守卫的全面解析

  1. 导航被触发
  2. 在失活的组件里调用 beforeRouteLeave 守卫
  3. 调用全局 beforeEach 守卫
  4. 在复用组件里调用 beforeRouteUpdate 守卫
  5. 调用路由配置的 beforeEnter守卫
  6. 解析异步路由组件
  7. 在被激活的组件里面调用 beforeRouteEnter 守卫
  8. 调用全局 beforeResolve 守卫
  9. 导航被确认
  10. 调用全局的 afterEach 钩子
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中,传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

10. vue-router 如何响应路由参数的变化

使用 watch 监听

  • 1)监听路由路由是否变化 2)或者 设置路径变化时的处理函数
  • 为了实现这样的效果可以给 < router-view > 组件中添加 key
<router-view :key="$route.fullPath"></router-view>
  • $route.fullPath 是完成后解析的 URL,包含其查询参数信息和 hash 完整路径

使用组件内的守卫(钩子函数) beforeRouteUpdate (to, from, next){ }

  • to : Route :表示 即将进入的目标 (路由对象)
  • from : Route :表示:当前导航正要离开的路由
  • next可选参数): Function: 确保 next 在任何给定的导航守卫中都被严格调用一次

11. 切换到新路由时,页面要滚动到顶部,或保持原先的位置,怎么实现

使用 scrollBehavior

12. 什么场景下使用嵌套路由

在页面点击不同的选项,需要切换不同的路由,来展示不同的内容时

13. 如何获取路由传入的参数

使用 params 方式传入的参数,使用 this.$route.params 接收

使用 query 方式传入的参数,使用 this.$route.query 接收

path、fullPath、hash 同上,this.$route.(path / fullPath / hash)

14. active-class 是哪个组件的属性

router-link

15. 在 Vue 组件中怎么获取当前的路由信息

this.$route

16. 怎么动态加载路由

使用 vue-router 的 addRoutes 方法

17. 怎么实现路由的懒加载

一般使用箭头函数的方法

components: () => import (' 组件路径 ')

import Vue from 'vue'
import VueRouter from 'vue-router'
 
Vue.use(VueRouter)
const router = new VueRouter({
 routes: [
    { path: '/login', component: () => import('@/views/login/index.vue') },
    { path: '/home',  component: () => import('@/views/home/home.vue') }
  ]
 
export default router

18. 简述一下怎么写一个 Vue 路由

  • 先在 page 文件夹创建一个 .vue 文件,写相关逻辑
  • 在 router.js 配置路由信息
  • 在相应的页面使用

19. 路由之间是怎么跳转的?

  • < router-link to=" 跳转到指定的路径 " >

  • this.$router.push( )

    • 跳转到指定的 URL ,并在 history 中添加记录,点击回退,返回到上一个页面
  • this.$router.replace( )

    • 跳转到指定的 URL , 但不在 history 中添加记录,点击回退,返回到上上个页面
  • this.$router.go( n )

    • 向前或者向后跳转 n 个页面,n 可为正整数或负整数

20. 创建路由

第一步:创建

  • 在 views 文件夹下,创建 XXX.vue 文件

第二步:引入并注册

  • 在 router / index.js 文件中
// 引入最基本的两个文件 Vue 和 VueRouter
import Vue from 'vue'
import VueRouter from 'vue-router'// 引入组件
import LoginIndex from '@/views/Login/LoginIndex.vue'// 1. 安装插件 VueRouter
// 2. Vue.use()函数的作用:使用插件
Vue.use(VueRouter)
​
// routes[] 的作用:定义 hash地址 与 组件 之间的对应关系
const routes = [
  // 路由重定向
  {
    path: '/',
    redirect: '/home'       
  },
  
  // 注册路由
  {
    path: '/login',         // 自己设置的路由路径
    name: 'login',          // 路由名称
    component: LoginIndex,  // 要展示的组件(引入组件的时候,命名的)
    meta: { show: true }    // 路由元信息
  }
]
​
// 创建路由实例对象
const router = new VueRouter({
  // 专门存放路由配置的数组
  routes
})
​
// 对外暴露
export default router
​

第三步:使用

<router-link to="/login" target="_blank"><button>登录</button></router-link>

21. 路由传参的几种写法

定义

  • params 参数:属于路径的一部分,配置路由的时候,需要占位

    {
        path: 'goods/:id/:title'
    }
    ​
    // 相当于 $route 上的属性使用
    {{ $route.params.id }}
    {{ $route.params.title }}
    
  • query 参数:不属于路径的一部分,类似于 Ajax 中的 queryString (/home?k=v&kv=),不需要占位

    // 相当于 $route 上的属性使用
    {{ $route.query.id }}
    {{ $route.query.title }}
    

使用时的3种方式

  • 第一种:字符串形式

  • 基本语法

    this.$router.push("/search/" + params参数 + "?自定义名称=" + query参数 );
    ​
    this.$router.push("/search/" + this.keyword + "?k=" + this.keyword.toUpperCase());
    
  • 第二种:模板字符串, 较为方便

  • 基本语法

    this.$router.push(`/search/${ params参数 }? 自定义名称 =${ query参数 }`);
    ​
    this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`);
    
  • 第三种:对象,常用

  • 基本语法

    this.$router.push( {name【可以换成 path】:"路由组件名称", params:{自定义名称:this.keyword}, query:{自定义名称:this.keyword.toUpperCase()}} );
    ​
    this.$router.push({name:"search", params:{keyword:this.keyword}, query:{k:this.keyword.toUpperCase()}});
    ​
    this.$router.push({path:"search", params:{keyword:this.keyword}, query:{k:this.keyword.toUpperCase()}});
    

代码实现

// 在Header组件中
// 业务:点击搜索按钮,跳转到搜索页面,并将相关数据传递过去
<template>
    <!-- 搜索栏 -->
    <input type="text" placeholder="请输入关键字" v-model="keyword" />
    <button class="btn-search" @click="gotoSearch">搜索</button>
</template><script>
export default {
  name: "",
  // 数据
  data() {
    return {
      keyword: ''
    }
  },
  // 方法
  methods: {
    // 跳转到搜索页
    gotoSearch() {
      // 路由传参
      
      // 第一种:字符串形式
      // this.$router.push("/search/" + this.keyword + "?k=" + this.keyword.toUpperCase());
      
      // 第二种:模板字符串
      // this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`);
​
      // 第三种:对象
      this.$router.push({name:"search", params:{keyword:this.keyword}, query:{k:this.keyword.toUpperCase()}});
    }
  },
};
</script>
​
样式:略
​
// router / index.js 文件
{   // 注册组件
    path: '/search/:keyword',   // 接收params参数,需要进行占位
    name: 'search',             // 设置名称,使用对象写法时,要用上
    component: Search
}

路由传参相关面试题

路由传递参数(对象写法)path 是否可以结合 params 参数一起使用?

答:路由跳转传参的时候,对象写法有两种 name | path,但是 path 写法不能和 params 参数一起使用;name 写法可以

如何指定 params 参数可传可不传?

答:如果路由要求传递 params 参数,但是你就不传,URL 会有问题;

http://localhost:8080/#/?k=QWE// 如果硬是不传params参数,会导致页面即使跳转到了 Search页面,但是路径却没有显示 “search”

若要指定 params 参数可以传递、或者不传递,在配置路由的时候,在占位的后面加上一个问号

代码:

// 在配置路由的文件中 router/index.js
{
    path: '/search/:keyword?',   // 添加 ? 指定params参数可传,可不传
    name: 'search',
    component: Search
}
​
// 在对应的组件中
this.$router.push({name:"search", query:{k:this.keyword.toUpperCase()}});

params 参数可以传递也可以不传递,但是如果传递是空串,如何解决?

  • 如果传递空串会出现上诉 “search” 丢失的路径问题
  • 使用 undefined 解决 路径丢失的问题
this.$router.push({name:"search", params:{keyword:'' || undefined}, query:{k:this.keyword.toUpperCase()}});
this.$router.push({name:'search', params:{keyword:''||undefined}query:{k:this.keyword.toUpperCase()}});

路由组件能不能传递 props 数据?

  • 可以,有三种写法。

第一种:布尔值写法【params】【只能传 params 参数】

// 在配置路由的文件
{
    path: '/search/:keyword?',   // 接收params参数,需要进行占位,  ? 指定params参数可传,可不传
    name: 'search',
    component: Search,
    props: true                 // 将 Search 组件设置成可以接收 props数据,但是只能传params参数
}
​
// 在 Search 组件
<template>
    <div class="body">
        <h1>我是搜索页</h1>
        <h2>params参数---{{keyword}}</h2>
    </div>
</template>
​
<script>
export default {
    name: '',
    props: ['keyword']
}
</script>

第二种写法:对象写法【额外给路由组件传递 props,而且是固定值】

// 在配置路由的文件中
  {
    path: '/search/:keyword?',   // 接收params参数,需要进行占位, ? 指定params参数可传,可不传
    name: 'search',
    component: Search,
    props: { a: 1, b: 2}        // 对象写法,额外给路由组件传递的值,而且是固定值
  }
  
// 在 Search 组件
<template>
    <div class="body">
        <h1>我是搜索页</h1>
        <h2>额外传递的值----{{a}}-----{{b}}</h2>
    </div>
</template>
​
<script>
export default {
    name: '',
    props: ['a', 'b']
}
</script>

第三种写法:函数写法【最常用,可以把 params 参数、query 参数,通过 props 传递给路由组件】

// 在配置路由的文件中
  {
    path: '/search/:keyword?',   // 接收params参数,需要进行占位, ? 指定params参数可传,可不传
    name: 'search',
    component: Search,
    // 函数写法
    props: ($route)=> {
      return {
        keyword: $route.params.keyword,
        k: $route.query.k
      };
    }
  }
  
// 在 Search 组件
<template>
    <div class="body">
        <h1>我是搜索页</h1>
        <h2>params参数------{{keyword}}</h2>
        <h2>query参数---{{k}}</h2>
    </div>
</template>
​
<script>
export default {
    name: '',
    props: ['keyword', 'k']
}
</script>