Vue-Router 面试题汇总

1,121 阅读5分钟

Vue-Router 面试题汇总

参考文献

1. 怎么重定向页面

第一种:

const router = new VueRouter({
    routes: [
        { path: '/a', redirect: '/b' } // 可以是路径
    ]
})

第二种:

const router = new VueRouter({
    routes: [
        { path: '/a', redirect: { name: 'foo' }} // 也可以是组件名
    ]
})

第三种:

const router = new VueRouter({
    routes: [
        { 
            path: '/a', 
            redirect: to =>{
                const { hash, params, query } = to
                if (query.to === 'foo') {
                    return { path: '/foo', query: null }
                }else{
                   return '/b' 
                }
            }
            
        }
    ]
})

2. 怎么配置404页面

const router = new VueRouter({
    routes: [
        {
            path: '*', redirect: {path: '/'}
        }
    ]
})

3. 路由两种模式的区别

  • hash: 兼容所有浏览器,包括不支持 HTML5 History Api 的浏览器,例www.abc.com/#/index,has… hash的改变会触发hashchange事件,通过监听hashchange事件来完成操作实现前端路由。hash值变化不会让浏览器向服务器请求。
// 监听hash变化,点击浏览器的前进后退会触发
window.addEventListener('hashchange', function(event){ 
    let newURL = event.newURL; // hash 改变后的新 url
    let oldURL = event.oldURL; // hash 改变前的旧 url
},false)
复制代码
  • history: 兼容能支持 HTML5 History Api 的浏览器,依赖HTML5 History API来实现前端路由。没有#,路由地址跟正常的url一样,但是初次访问或者刷新都会向服务器请求,如果没有请求到对应的资源就会返回404,所以路由地址匹配不到任何静态资源,则应该返回同一个index.html 页面,需要在nginx中配置。

4. 导航守卫流程

  • 导航被触发。

  • 在失活的组件里调用离开守卫beforeRouteLeave(to,from,next)

  • 调用全局的beforeEach( (to,from,next) =>{} )守卫。

  • 在重用的组件里调用 beforeRouteUpdate(to,from,next) 守卫。

  • 在路由配置里调用beforeEnter(to,from,next)路由独享的守卫。

  • 解析异步路由组件。

  • 在被激活的组件里调用beforeRouteEnter(to,from,next)

  • 在所有组件内守卫和异步路由组件被解析之后调用全局的beforeResolve( (to,from,next) =>{} )解析守卫。

  • 导航被确认。

  • 调用全局的afterEach( (to,from) =>{} )钩子。

  • 触发 DOM 更新。

  • 用创建好的实例调用beforeRouteEnter守卫中传给 next 的回调函数

beforeRouteEnter(to, from, next) {
    next(vm => {
        //通过vm访问组件实例
    })
},

5. 路由导航守卫和Vue生命周期钩子函数的执行顺序?

路由导航守卫都是在Vue实例生命周期钩子函数之前执行的。

6. 导航守卫三个参数的含义

to:即将要进入的目标 路由对象。

from:当前导航正要离开的路由对象。

next:函数,必须调用,不然路由跳转不过去。

  • next():进入下一个路由。
  • next(false):中断当前的导航。
  • next('/')next({ path: '/' }) : 跳转到其他路由,当前导航被中断,进行新的一个导航。

7. afterEach 钩子中可以使用 next()

不可以,不接受next参数

8. 全局导航守卫有哪些

  • router.beforeEach:全局前置守卫。
  • router.beforeResolve:全局解析守卫。
  • router.afterEach:全局后置钩子。
import VueRouter from 'vue-router';
const router = new VueRouter({
    mode: 'history',
    base: '/',
    routes,
    // 新页面滚动到顶部
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return savedPosition;
        } else {
            return { x: 0, y: 0 };
        }
    }

作者:红尘炼心
链接:https://juejin.cn/post/6844903961745440775
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
})
router.beforeEach((to, from, next) => {
    //...
    next();
})
router.beforeResolve((to, from, next) => {
    //...
    next();
})
router.afterEach((to, from) => {
    //...
});

9. 组件内使用的导航守卫有哪些

  • beforeRouteLeave:在失活的组件里调用离开守卫。
  • beforeRouteUpdate:在重用的组件里调用,比如包含<router-view />的组件。
  • beforeRouteEnter:在进入对应路由的组件创建前调用。
beforeRouteLeave(to, from, next) {
    //...
},
beforeRouteUpdate(to, from, next) {
    //...
},
beforeRouteEnter(to, from, next) {
    //...
},

10. 对router-link的了解

<router-link>是Vue-Router的内置组件,在具有路由功能的应用中作为声明式的导航使用。

<router-link>有8个props,其中几个作用是:

  • to:必填,表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

    <router-link to="home">Home</router-link><router-link :to="'home'">Home</router-link><router-link :to="{ path: 'home' }">Home</router-link><router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link><router-link :to="{ path: 'user', query: { userId: 123 }}">User</router-link>
    

    注意path存在时params不起作用,只能用query

  • replace:默认值为false,若设置的话,当点击时,会调用router.replace()而不是router.push(),于是导航后不会留下 history 记录。

  • append:设置 append 属性后,则在当前 (相对) 路径前添加基路径。

  • exact:是否精确匹配,默认为false。

    <!-- 这个链接只会在地址为 / 的时候被激活 --><router-link to="/" exact></router-link>
    
  • event:声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组,默认是click

11. 在组件中监听路由参数变化

有两种方法可以监听路由参数的变化,但是只能用在包含<router-view />的组件内。

  • 第一种 watch

    watch: {    '$route'(to, from) {        //这里监听    },},
    
  • 第二种 beforeRouteUpdate

    beforeRouteUpdate (to, from, next) {    //这里监听},
    

12. 嵌套路由的使用

比如管理系统,顶部栏和左侧菜单栏是全局通用的,那就应该放在父路由,而右下的页面内容部分放在子路由。

app.vue

<template>  <div>    <router-view/>  </div></template>

layout.vue

<template>  <div>    <div>        //...头部导航    </div>    <div>        //...侧边栏导航    </div>    <div>        //...主内容        <router-view/>    </div>  </div></template

13. 命名视图

比如想同级展示多个视图,而不是嵌套展示。例如项目首页,有头部导航,侧边栏导航、主内容区域。头部导航、侧边栏导航我们不想用组件方式引入,想用视图方式展示。那么这个首页上,就有三个视图,头部导航视图,侧边栏导航视图、主内容区域视图同级展示。

layout.vue

<template>  <div>    <div>        //...头部导航        <router-view name='header'></router-view>    <div>        //...侧边栏导航        <router-view name='sider'></router-view>    </div>    <div>        //...主内容        <router-view/>    </div>  </div></template>

如果 router-view 没有设置name,那么默认为default。一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (记得加上s)。

router.js

function load(component) {
    return resolve => require([`views/${component}`], resolve);
}
const routes=[
    {
        path: '/',
        redirect: '/home',
        name: 'layout',
        component: load('layout'),
        children: [
            {
                path: '/home',
                name: 'home',
                components: {
                    default: load('main'),
                    header: load('header'),
                    sider: load('sider')
                },
                meta: {
                    title: '首页'
                },
            },
        ]
    }
]

14. 获取路由传参

  • query:
this.$route.push({
    path:'/home',
    query:{
        userId:123
    }
})
复制代码

浏览器地址:http://localhost:8036/home?userId=123 获取方式:this.$route.query.userId

  • params:

    (1) 首先要在地址上做配置

{
    path: '/home/:userId',
    name: 'home',
    component: load('home'),
    meta: {
        title: '首页'
    },
},

​ (2) 访问传参

const userId = '123'
this.$router.push({ name: 'home', params: { userId } })

注意用params传参,只能用命名的路由(用name访问),如果用path,params不起作用。this.$router.push({ path: '/home', params: { userId }})不生效。

​ (3) 浏览器地址:http://localhost:8036/home/123 ​ (4) 获取方式:this.$route.params.userId

15. 路由跳转的方式

  • 声明式 通过使用内置组件<router-link :to="/home">来跳转

  • 编程式 通过调用router实例的push方法router.push({ path: '/home' })或replace方法router.replace({ path: '/home' })

16. 使用history模式部署要注意什么

要注意404的问题,因为在history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求,当直接在浏览器里输入这个地址的时候,就一定要对服务器发起http请求,但是这个目标在服务器上又不存在,所以会返回404。

所以要在Ngnix中将所有请求都转发到index.html上就可以了。

17. route和router区别

route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。

而router是“路由实例对象”,包括了路由的跳转方法,钩子函数等。