Vue-Router面试题汇总

怎么重定向页面?

第一种方法:

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' 
                }
            }
            
        }
    ]
})

怎么配置404页面?

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

切换路由时,需要保存草稿的功能,怎么实现呢?

<keep-alive :include="include">
    <router-view></router-view>
 </keep-alive>

其中include可以是个数组,数组内容为路由的name选项的值。

路由有几种模式?说说它们的区别?

hash: 兼容所有浏览器,包括不支持 HTML5 History Api 的浏览器,例http://www.abc.com/#/index,hash值为#/index, 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中配置。
abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

讲一下完整的导航守卫流程?

导航被触发。
在失活的组件里调用离开守卫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访问组件实例
})
},

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

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

讲一下导航守卫的三个参数的含义?

to:即将要进入的目标 路由对象。
from:当前导航正要离开的路由对象。
next:函数,必须调用,不然路由跳转不过去。

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

在afterEach钩子中可以使用next()吗?

不可以,不接受next的参数。

全局导航守卫有哪些?怎么使用?

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 };
        }
    }
})
router.beforeEach((to, from, next) => {
    //...
    next();
})
router.beforeResolve((to, from, next) => {
    //...
    next();
})
router.afterEach((to, from) => {
    //...
});

什么是路由独享的守卫,怎么使用?

是beforeEnter守卫

const router = new VueRouter({
    routes: [
        {
            path: '/foo',
            component: Foo,
            beforeEnter: (to, from, next) => {
            // ...
            }
        }
    ]
})

在组件内使用的导航守卫有哪些?怎么使用?

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

beforeRouteLeave(to, from, next) {
    //...
},
beforeRouteUpdate(to, from, next) {
    //...
},
beforeRouteEnter(to, from, next) {
    //...
},

在beforeRouteEnter导航守卫中可以用this吗?

不可以,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
可以通过传一个回调给next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter(to, from, next) {
    next(vm => {
        console.log(vm)
    })
}

说说你对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 属性后,则在当前 (相对) 路径前添加基路径。
tag:让<router-link>渲染成tag设置的标签,如tag:'li,渲染结果为<li>foo</li>。
active-class:默认值为router-link-active,设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
exact-active-class:默认值为router-link-exact-active,设置链接被精确匹配的时候应该激活的 class。默认值可以通过路由构造函数选项 linkExactActiveClass 进行全局配置的。
exact:是否精确匹配,默认为false。

<router-link to="/" exact></router-link>

event:声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组,默认是click。

怎么在组件中监听路由参数的变化?

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

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

切换路由后,新页面要滚动到顶部或保持原先的滚动位置怎么做呢?

滚动顶部const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return { x: 0, y: 0 };
}
}
});
复制代码
滚动原先位置

在什么场景下会用到嵌套路由?

做个管理系统,顶部栏和左侧菜单栏是全局通用的,那就应该放在父路由,而右下的页面内容部分放在子路由。
比如在app.vue文件中
<template>
<div>
<router-view/>
</div>
</template>
复制代码在layout.vue文件中
<template>
<div>
<div>
//...头部导航
</div>
<div>
//...侧边栏导航
</div>
<div>
//...主内容
<router-view/>
</div>

</div>
</template
复制代码在routes.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',
component: load('home'),
meta: {
title: '首页'
},
},
]
}
]
复制代码然后layout页面就渲染在app.vue文件中的<router-view/>上。home页面就渲染在layout.vue文件夹中的<router-view/>上。

什么是命名视图,举个例子说明一下?

在项目中,我们想同级展示多个视图,而不是嵌套展示。例如项目首页,有头部导航,侧边栏导航、主内容区域。头部导航、侧边栏导航我们不想用组件方式引入,想用视图方式展示。那么这个首页上,就有三个视图,头部导航视图,侧边栏导航视图、主内容区域视图同级展示。
在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)。
在routes.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: '首页'
},
},
]
}
]
复制代码
如何获取路由传过来的参数?

路由有三种传参方式,获取方式各不相同。

meta:路由元信息,写在routes配置文件中。{
path: '/home',
name: 'home',
component: load('home'),
meta: {
title: '首页'
},
},
复制代码获取方式this.route.meta.title获取 query:this.route.push({
path:'/home',
query:{
userId:123
}
})
复制代码浏览器地址:http://localhost:8036/home?userId=123
获取方式:this.$route.query.userId
params:这种方式比较麻烦。

首先要在地址上做配置{
path: '/home/:userId',
name: 'home',
component: load('home'),
meta: {
title: '首页'
},
},
复制代码
访问传参const userId = '123'
this.router.push({ name: 'home', params: { userId } }) 复制代码注意用params传参,只能用命名的路由(用name访问),如果用path,params不起作用。 this.router.push({ path: '/home', params: { userId }})不生效。
浏览器地址:http://localhost:8036/home/123
获取方式:this.$route.params.userId

路由组件和路由为什么解耦,怎么解耦?

因为在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性,所有要解耦。

耦合如以下代码所示。Home组件只有在http://localhost:8036/home/123URL上才能使用。const Home = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/home/:id', component: Home }
]
})
复制代码
使用 props 来解耦

props为true,route.params将会被设置为组件属性。
props为对象,则按原样设置为组件属性。
props为函数,http://localhost:8036/home?id=123,会把123传给组件Home的props的id。

const Home = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/home/:id', component: Home, props: true},
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 props 选项:
{
path: '/home/:id',
components: { default: Home, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
{ path: '/home', component: Home, props: {id:123} },
{ path: '/home', component: Home, props: (route) => ({ id: route.query.id }) },
]
})
复制代码

说说active-class是哪个组件的属性?

<router-link/>组件的属性,设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。

在vue组件中怎么获取到当前的路由信息?

通过this.$route来获取

怎样动态加载路由?

使用Router的实例方法addRoutes来实现动态加载路由,一般用来实现菜单权限。
使用时要注意,静态路由文件中不能有404路由,而要通过addRoutes一起动态添加进去。
const routes = [
{
path: '/overview',
name: 'overview',
component: () => import('@/views/account/overview/index'),
meta: {
title: '账户概览',
pid: 869,
nid: 877
},
},
{
path: '*',
redirect: {
path: '/'
}
}
]
vm.router.options.routes.push(...routes); vm.router.addRoutes(routes);
复制代码
怎么实现路由懒加载呢?

function load(component) {
//return resolve => require([views/${component}], resolve);
return () => import(views/${component});
}

const routes = [
{
path: '/home',
name: 'home',
component: load('home'),
meta: {
title: '首页'
},
},
]
复制代码
路由之间是怎么跳转的?有哪些方式?

声明式 通过使用内置组件<router-link :to="/home">来跳转
编程式 通过调用router实例的push方法router.push({ path: '/home' })或replace方法router.replace({ path: '/home' })

如果vue-router使用history模式,部署时要注意什么?

要注意404的问题,因为在history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求,当直接在浏览器里输入这个地址的时候,就一定要对服务器发起http请求,但是这个目标在服务器上又不存在,所以会返回404。
所以要在Ngnix中将所有请求都转发到index.html上就可以了。
location / {
try_files uriuri/ @router index index.html;
}
location @router {
rewrite ^.*$ /index.html last;
}
复制代码
route和router有什么区别?

route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。 而router是“路由实例对象”,包括了路由的跳转方法,钩子函数等。

Vue路由怎么跳转打开新窗口?

const obj = {
path: xxx,//路由地址
query: {
mid: data.id//可以带参数
}
};
const {href} = this.$router.resolve(obj);
window.open(href, '_blank');

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容