【校招VIP】vue-Router 常见面试题

08月24日 收藏 0 评论 0 前端开发

【校招VIP】vue-Router 常见面试题

转载声明:文章来源:https://blog.csdn.net/weixin_59395272/article/details/131304998

vue-router 路由钩子函数是什么 执行顺序是什么
钩子函数种类有:全局守卫、路由守卫、组件守卫
全局钩子:beforeEach、beforeResolve、afterEach
beforeEach 全局前置守卫 初始化时执行,每次路由切换前执行。全局前置守卫通常用来进行路由跳转的一些信息判断,判断是否登录,是否拿到对应的路由权限等等。
afterEach 全局后置守卫 初始化时执行,每次路由切换后执行。对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
beforeResolve 全局解析守卫
路由独享的守卫:beforeEnter
组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
完整的导航解析流程:
1、导航被触发
2、在失活的组件里调用 离开守卫 beforeRouteLeave
3、调用 全局前置守卫 beforeEach
4、在重用的组件里调用 更新守卫beforeRouteUpdate (2.2+)(举例来说,对于一个带有动态参数的路径 /user/:id,在 /users/1 和 /users/2 之间跳转的时候,由于会渲染同样的 UserDetail 组件,因此组件实例会被复用。而这个守卫就会在这个情况下被调用)
5、在路由配置规则里调用 独享守卫 beforeEnter
6、解析异步路由组件
7、在被激活的组件里调用 进入守卫 beforeRouteEnter
8、调用全局解析守卫 beforeResolve (2.5+)(和 全局前置守卫router.beforeEach 类似,因为它在每次导航时都会触发,但是确保在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被正确调用)
9、导航被确认
10、调用全局后置守卫 afterEach
11、触发 DOM 更新
12、调用 进入守卫 beforeRouteEnter中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

路由传参的几种方式
传参方式可划分为params 传参 和query传参,而params传参可以分为在url地址栏当中显示参数和不显示参数两种方式
一、query 传参(显示参数,刷新页面不丢失)
1、path 和 query 组合使用
声明式

声明式

路由配置
{
path: '/bounceBall',
name: 'bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}

页面使用
<router-link :to="{ path: 'bounceBall', query: { id: 1 } }">看动画</router-link>

编程式 this.$router.push

路由配置:
{
path: '/bounceBall',
name: 'bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}


页面应用
<el-button type="primary" @click="() => { $router.push({ path: 'bounceBall', query: { id: 1 } }) } " >看动画</el-button >

2、name 和 query 组合使用
声明式router-link:该方式是通过 router-link 组件的 to 属性实现,不过使用该方式传值的时候,需要子路由提前配置好路由别名

路由配置
{
path: '/bounceBall',
name: 'bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}

页面使用
<router-link :to="{ name: 'bounceBall', query: { id: 1 } }">看动画</router-link>

编程式 this.$router.push:使用该方式传值的时候,同样需要子路由提前配置好路由别名(name 属性)

路由配置:
{
path: '/bounceBall',
name: 'bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}


页面应用
<el-button type="primary" @click="() => { $router.push({ name: '/bounceBall', query: { id: 1 } }) } " >看动画</el-button >

3、使用 ?拼接路径的

{
path: '/bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}

声明式使用
<router-link to="/bounceBall?id=1">看动画</router-link>

编程式
<el-button type="primary" @click=" () => { $router.push('/bounceBall?id=1') }">看动画</el-button>

以上的接收方式都是:this.$route.query.id
二、params 传参
1、只使用path (显示参数),刷新不丢失参数
声明式router-link:该方式是通过router-link组件的to属性实现,子路由需要提前配置好参数

编程式 this.$router.push:同样需要子路由提前配置好参数。

接收: this.$route.params.id
2、name 和 params 组合使用(不显示参数,刷新页面数据会丢失,刷新页面后this.$route.params为空对象)

(只能通过name 不能通过path,path中拿不到params的值,并且使用name刷新页面会都丢失数据 )
主要来源:路由传参的几种方式 亲测有效!!!!_郝程序猿的博客-CSDN博客

Vue-Router 的懒加载
路由懒加载的含义:把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件。

{
path: '/bounceBall',
name: 'bounceBall',
component: () => import('@/components/animation/bounceBall.vue')
}

vue-router 中常用的路由模式
hash模式
location.hash 的值实际就是 URL 中#后面的东西 它的特点在于:hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
可以为 hash 的改变添加监听事件
window.addEventListener("hashchange", funcRef, false);
每一次改变 hash(window.location.hash),都会在浏览器的访问历史中增加一个记录利用 hash 的以上特点,就可以来实现前端路由“更新视图但不重新请求页面”的功能了
特点:兼容性好但是不美观
history 模式
利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。
这两个方法应用于浏览器的历史记录站,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前 URL 改变了,但浏览器不会刷新页面,这就为单页应用前端路由“更新视图但不重新请求页面”提供了基础。
特点:虽然美观,但是刷新会出现 404 需要后端进行配置(一般是将页面配置重定向到首页路由)
总结
hash模式是开发中默认的模式,如果想要切换到history模式,就要进行以下配置(后端也要进行配置):
const router = new VueRouter({
mode: 'history',
routes: [...]
})

route和router 的区别
$route对象:$route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等。
1. $route.path 字符串,对应当前路由的路径,总是解析为绝对路径,如"/foo/bar"。
2. $route.params 一个 key/value 对象,包含了 动态片段 和 全匹配片段, 如果没有路由参数,就是一个空对象。
3. $route.query 一个 key/value 对象,表示 URL 查询参数。 例如,对于路径 /foo?user=1,则有$route.query.user == 1, 如果没有查询参数,则是个空对象。
4. $route.hash 当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串。锚点*
5. $route.fullPath 完成解析后的 URL,包含查询参数和hash的完整路径。
6. $route.matched 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
7. $route.name 当前路径名字
8. $route.meta 路由元信息
$router对象:$router对象是全局路由的实例,是router构造方法的实例。
实例方法:
1、push
1.字符串this.$router.push('home')
2. 对象this.$router.push({path:'home'})
3. 命名的路由this.$router.push({name:'user',params:{userId:123}})
4.带查询参数,变成 /register?plan=123this.$router.push({path:'register',query:{plan:'123'}})
push方法其实和<router-link :to="...">是等同的。
注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
2、go
页面路由跳转
前进或者后退this.$router.go(-1) // 后退
3、replace
push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录

单页面应用的优缺点(SPA)
单页面应用程序将所有的活动局限于一个Web页面中,在该Web页面初始化时加载相应的HTML、JavaScript 和 CSS。一旦页面加载完成,单页面应用不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用 JavaScript 动态的变换HTML的内容,从而实现UI与用户的交互。由于避免了页面的重新加载,单页面应用可以提供较为流畅的用户体验。
所谓的页面跳转,多个页面之间的切换是利用JS动态的变换HTML的内容,加载的时候不是加载整个页面,而是某个指定的容器中的内容。
一个例子:你有一个水杯,一会儿装的是可乐,一会儿装的是牛奶。
单页面应用的优点
良好的交互体验
单页应用的内容的改变不需要重新加载整个页面,获取数据也是通过Ajax异步获取,没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并有“闪烁”现象,页面显示流畅
良好的前后端工作分离模式
后端不再负责模板渲染、输出页面工作,后端API通用化,即同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端
减轻服务器压力
单页应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍
缺点
不会记住用户的操作记录
首屏加载慢
解决方案:
1.vue-router懒加载
Vue-router懒加载就是按需加载组件,只有当路由被访问时才会加载对应的组件,而不是在加载首页的时候就加载,项目越大,对首屏加载的速度提升得越明显
2.使用CDN加速
在做项目时,我们会用到很多库,采用cdn加载可以加快加载速度。
3.异步加载组件
4.服务端渲染
服务端渲染还能对seo优化起到作用,有利于搜索引擎抓取更多有用的信息(如果页面纯前端渲染,搜索引擎抓取到的就只是空页面)
不利于SEO
seo 本质是一个服务器向另一个服务器发起请求,解析请求内容。但一般来说搜索引擎是不会去执行请求到的js的。也就是说,搜索引擎的基础爬虫的原理就是抓取url,然后获取html源代码并解析。 如果一个单页应用,html在服务器端还没有渲染部分数据数据,在浏览器才渲染出数据,即搜索引擎请求到的html是模型页面而不是最终数据的渲染页面。 这样就很不利于内容被搜索引擎搜索到
解决方案:
1.服务端渲染
服务器合成完整的 html 文件再输出到浏览器
2.页面预渲染
3.路由采用h5 history模式

后台管理系统的前端权限控制与管理
1、前端权限控制思路
1.1.菜单的控制
在登录请求中,会得到权限数据,当然,这个需要后端返回数据的支持前端根据权限数据,展示对应的菜单.点击菜单才能查看相关的界面.(不同用户的菜单列表不一样)
1.2.界面的控制
如果用户没有登录,手动在地址栏敲入管理界面的地址,则需要跳转到登录界面
如果用户已经登录可是手动敲入非权限内的地址,则需要跳转404界面
1.3.按钮的控制
在某个菜单的界面中,还得根据权限数据,展示出可进行操作的按钮,比如删除,修改,增加
1.4.请求和响应的控制
如果用户通过非常规操作,比如通过浏览器调试工具将某些禁用的按钮变成启用状态,此时发的请求,也应该被前端所拦截
2、实践
(1)菜单的控制
一般来说,菜单的控制都会让后端在登录请求后存放在res.rights中,权限数组中的authName和children中的authName对应的就是用户所拥有的权限菜单
在用户进行登录的时候,将权限列表保存到vuex中,在vuex中定义一个mutation来对rightsList进行保存
在create生命周期中将获取的rightsList存放到data中的menulist中给菜单组件渲染(假如后端返回的数据不能直接给rightsList展示,可以在这里对返回的数据处理成方便渲染的数据)
问题:页面一刷新vuex中的数据会被清空,这时我们又没有到登录界面去登录所以没有将数据存放在vuex中。会造成一刷新页面菜单栏为空的现象
解决方法: 登录时将权限内容保存到sessionStorage中(sessionStorage中存放的是字符串),在state中通过sessionStorage.getItem去获取rightsList中的内容没有就给空数组
(2)界面的控制
在登录后可以将token保存起来
利用路由导航守卫对有无登录做出对应页面跳转
重点:动态路由的渲染
将路由规则提取成变量
把路由规则的变量做映射,对应后端返回的路由path
使用router.options.routes可以获取当前的路由规则
使用router.addRoutes()可以更新修改后的路由规则
(3)按钮的控制
用户不具备权限的按钮就隐藏或者禁用,而在这块中,可以把该逻辑放到自定义指令中 permission.js
通过Vue.directive创建自定义指令
inserted()是元素插入dom节点时触发,其中el是指当前的元素,binding是获取自定义指令中的数据内容
在渲染动态路由时就有将路由对应的权限保存在meta中。此时再判断自定义指令中是否存在当前路由的meta中的权限,如果没有那么移除权限,如果有并且自定义指令中有disable那么可以让元素不可选中。
(4)请求和响应的控制
请求控制
除了登录请求都得要带上token,在封装请求时(axios),做统一处理。

C 0条回复 评论

帖子还没人回复快来抢沙发