- 单页应用和多页应用的区别是什么?
- Vue Router中如何监听路由变化,有几种方式?
- Vue Router中有哪些路由模式,它们有什么区别?
- Vue Router中页面跳转时,如何传递参数?
- Vue Router中实现页面跳转时,如何保存页面的状态?
5、 vue-router有哪几种导航钩子( 导航守卫 )?
9、 切换到新路由时,页面要滚动到顶部或保持原先的滚动位置怎么做呢?
10、 在什么场景下会用到嵌套路由?
11、 如何获取路由传过来的参数?
14、 vur-router怎么重定向?
15、 怎样动态加载路由?
16、 怎么实现路由懒加载呢?
20、 如果vue-router使用history模式,部署时要注意什么?
1.单页应用和多页应用的区别是什么?
单页应用(SPA)和多页应用(MPA)的核心区别如下:
1. 页面加载方式
- SPA:仅首次加载完整HTML/CSS/JS,后续内容通过JavaScript动态替换(如React/Vue路由切换),无页面刷新。
- MPA:每次跳转都向服务器请求新HTML页面,整页刷新。
2. 用户体验
- SPA:交互流畅(类似桌面应用),切换内容无白屏。
- MPA:每次跳转有短暂白屏,依赖网络速度。
3. 技术实现
- SPA:
- 前端框架(React/Angular/Vue)管理视图和状态。
- 后端仅提供API接口(前后端分离)。
- MPA:
- 后端渲染HTML(如PHP/JSP模板)。
- 前后端耦合度高(常混合业务逻辑)。
4. 性能特点
- SPA:
- 首屏较慢(需加载所有资源)。
- 后续操作快(仅请求数据)。
- MPA:
- 首屏较快(按需加载单个页面)。
- 重复加载资源(如公共CSS/JS)。
5. SEO优化
- SPA:传统SEO较弱(依赖JS渲染),需服务端渲染(SSR)或预渲染优化。
- MPA:天然SEO友好(静态HTML直接可抓取)。
适用场景
- SPA:后台管理系统、社交平台(如Gmail、Twitter)。
- MPA:内容型网站、电商平台(如新闻站、传统企业官网)。
一句话总结:
SPA用动态加载换流畅体验,MPA以整页刷新保简单直接。
2.Vue Router中如何监听路由变化,有几种方式?
3.Vue Router中有哪些路由模式,它们有什么区别?
(4)Vue Router中页面跳转时,如何传递参数?
(5)Vue Router中实现页面跳转时,如何保存页面的状态?
1、 vue-router怎么重定向页面?
redirect alias
方法一:在routes:[{
{ path: '/a', redirect: '/b' }
}]
方法二:别名
routes: [
{ path: '/a', component: A, alias: '/b' }
]
2、 vue-router怎么配置404页面?
将path:'*' , *放在最后,因为如果你放在前面会导致后面的的不能匹配
3、 切换路由时,需要保存草稿的功能,怎么实现呢?
用keep-alive缓存那个路由 或者本地缓存
在beforeDestroy中加入check功能, 当检测到有草稿时, 自动保存到vuex或者storage中或者window中等等 但是我要说的是, 这种方法是不靠谱的, 如果我是刷新页面呢! 建议采用, 实施保存操作, 保存在storage中较为靠谱, 当然这种操作牺牲是比较多的,可以用beforeDestroy结合window.onbeforeunload解决性能问题
4、 vue-router路由有几种模式?说说它们的区别?
结合vue3性能调优+deepseek
vue-router 支持三种路由模式:
-
Hash 模式
- URL 格式:
http://example.com/#/path - 通过 URL 中的
#后的哈希值实现路由,不触发页面刷新。 - 兼容性最好,支持所有浏览器,无需服务器配置。
- URL 格式:
-
History 模式
- URL 格式:
http://example.com/path(无#,更美观) - 基于 HTML5
history.pushStateAPI,需服务器配置支持(所有路径重定向到index.html),否则直接访问子路由会返回 404。
- URL 格式:
-
Abstract 模式
- 用于非浏览器环境(如 React Native、Electron),路由信息保存在内存中,不依赖 URL。
核心区别:
- Hash 模式兼容性强但 URL 带
#,History 模式 URL 更规范但需服务器配合,Abstract 模式用于非 Web 环境。
5、 vue-router有哪几种导航钩子( 导航守卫 )?
共有三种守卫:
1:全局前置守卫,全局解析守卫,全局后置钩子:beforeEach, beforeResolve,afterEach,
2:路由配置守卫:beforeEnter
3:组件独享守卫:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave
他们执行顺序:全局》路由》组件 除了afterEach全局后置外,其他的守卫中务必要调用next(),否则无法完成导航 还有注意全局前置守卫可以用来进行拦截,(登录拦截)
6、 说说你对router-link的了解
vue-router插件的其中一个组件, 用于跳转路由, 类似于a标签, 它一般也会渲染成a标签, 但是可以通过tag来变更默认渲染元素, 通过to来跳转。需
exact精确匹配
7、 vue-router如何响应路由参数的变化?
8、 你有看过vue-router的源码吗?说说看
9、 切换到新路由时,页面要滚动到顶部或保持原先的滚动位置怎么做呢?
通过router 的meta来记录需要保存滚动条的位置,在new VueRouter()时调用scrollBehavior(to, from, savedPosition) {return { x: 0, y: 0 }}的方法
10、 在什么场景下会用到嵌套路由?
举个例子,例如做个管理系统,顶部栏和左侧菜单栏是全局通用的,那就应该放在父路由,而右下的页面内容部分放在子路由
11、 如何获取路由传过来的参数?
如果使用query方式传入的参数使用this.$route.query 接收
如果使用params方式传入的参数使用this.$router.params接收
props也可以是一个函数,这个函数提供一个route参数,这样就可以将参数转换为另一种类型,将静态值与基于路由的值结合,
12、 说说active-class是哪个组件的属性?
active-class是vue-router模块的router-link组件中的属性,用来做选中样式的切换
13、 在vue组件中怎么获取到当前的路由信息?
在 Vue 组件中,可以通过 this.$route 获取当前的路由信息。this.$route 是一个包含当前路由状态的对象,提供了以下常用属性:
- path: 当前路由的路径(如
/user/123)。 - params: 动态路由参数(如
{ id: '123' })。 - query: 查询参数(如
{ name: 'John' })。 - hash: 当前路由的 hash 值(如
#section)。 - fullPath: 完整的 URL 路径(如
/user/123?name=John#section)。 - name: 路由名称(如果定义了)。
- matched: 当前路由匹配的所有路由记录数组。
示例
<template>
<div>
<p>当前路径: {{ $route.path }}</p>
<p>路由参数: {{ $route.params }}</p>
<p>查询参数: {{ $route.query }}</p>
<p>Hash: {{ $route.hash }}</p>
<p>完整路径: {{ $route.fullPath }}</p>
<p>路由名称: {{ $route.name }}</p>
</div>
</template>
<script>
export default {
mounted() {
console.log('当前路由信息:', this.$route);
}
}
</script>
监听路由变化
如果需要监听路由变化,可以使用 watch:
export default {
watch: {
'$route'(to, from) {
console.log('路由从', from.path, '变化到', to.path);
}
}
}
使用 useRoute(Vue 3 + Composition API)
在 Vue 3 中,可以使用 useRoute 钩子:
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
console.log('当前路径:', route.path);
}
}
通过这些方法,你可以轻松获取和监听当前路由信息。
15、 怎样动态加载路由?
在 Vue 中动态加载路由(Dynamic Route Addition)通常用于按需加载路由配置(如根据用户权限或应用状态),以下是详细的实现方法:
1. 核心方法:router.addRoute()
Vue Router 提供了 router.addRoute() 方法,允许在运行时动态添加路由。
适用场景:
- 根据用户权限动态注册路由
- 应用模块按需加载
- 延迟加载特定功能的路由
2. 基础实现步骤
(1) 定义静态路由(初始路由)
// router.js
import { createRouter, createWebHistory } from 'vue-router';
const staticRoutes = [
{
path: '/login',
component: () => import('./views/Login.vue')
}
];
const router = createRouter({
history: createWebHistory(),
routes: staticRoutes,
});
export default router;
(2) 动态加载路由
在需要时(如用户登录后、按钮点击时)动态添加路由:
// 在组件或逻辑层中
import router from './router';
// 示例:动态加载用户仪表盘路由
const loadDashboardRoute = async () => {
// 动态导入组件(懒加载)
const DashboardComponent = () => import('./views/Dashboard.vue');
// 添加新路由
router.addRoute({
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
meta: { requiresAuth: true }
});
// 可选:导航到新路由
router.push('/dashboard');
};
3. 动态加载嵌套路由
如果要为现有路由添加嵌套子路由,需指定父路由的 name:
// 假设已存在一个 name 为 'Admin' 的父路由
router.addRoute('Admin', { // 指定父路由名称
path: 'settings',
component: () => import('./views/AdminSettings.vue')
});
4. 结合权限控制的完整示例
(1) 定义动态路由表
// dynamicRoutes.js
export const asyncRoutes = [
{
path: '/admin',
name: 'Admin',
component: () => import('./views/Admin.vue'),
meta: { role: 'admin' },
children: [
{
path: 'users',
component: () => import('./views/AdminUsers.vue')
}
]
},
{
path: '/user',
name: 'User',
component: () => import('./views/User.vue'),
meta: { role: 'user' }
}
];
(2) 根据权限动态加载
// 在权限验证逻辑中
import { asyncRoutes } from './dynamicRoutes';
// 假设用户角色为 'admin'
const userRole = 'admin';
// 过滤有权限的路由
const allowedRoutes = asyncRoutes.filter(route =>
route.meta.role === userRole
);
// 动态添加路由
allowedRoutes.forEach(route => {
router.addRoute(route);
});
// 检查当前路径是否匹配新路由(避免停留在不存在的路径)
if (!router.currentRoute.value.matched.length) {
router.replace('/');
}
5. 动态移除路由
使用 router.removeRoute(routeName) 按名称移除路由:
// 移除 name 为 'Admin' 的路由及其子路由
router.removeRoute('Admin');
6. 验证动态路由是否生效
(1) 查看已注册路由
console.log(router.getRoutes());
(2) 检查路由是否存在
const routeExists = router.hasRoute('Dashboard'); // 根据路由名称检查
7. 注意事项
- 导航守卫处理:
动态添加路由后,若当前路径与新路由匹配,需手动触发router.push()或重定向。 - 避免重复添加:
使用router.hasRoute()检查路由是否已存在。 - 组件加载失败处理:
对动态导入 (import()) 添加错误回调:() => import('./views/Admin.vue') .catch(() => { console.error('组件加载失败'); // 返回一个错误组件或重定向 }) - 服务端渲染 (SSR):
动态路由需与服务端渲染逻辑兼容(如 Nuxt.js 的特定处理)。
8. 完整流程图
触发动态加载条件(如用户登录)
↓
加载动态路由配置(从 API 或本地)
↓
过滤有权限的路由
↓
遍历添加路由(router.addRoute())
↓
验证当前路径是否有效
↓
更新导航或跳转
通过动态加载路由,可以实现灵活的权限管理和代码分割优化!
16、 怎么实现路由懒加载呢?
在 Vue 中实现路由懒加载(也叫按需加载)可以显著减少应用的初始包体积,提升首屏加载速度。以下是具体的实现方法:
1. 基本实现(基于动态 import 语法)
使用 动态 import() 语法(ES6 标准)结合 Webpack 的代码分割功能,将路由组件按需加载:
// router.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/home',
name: 'Home',
component: () => import('./views/Home.vue'), // 动态导入组件
},
{
path: '/about',
name: 'About',
component: () => import('./views/About.vue'),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
- 原理:Webpack 会将
import()语法标记为代码分割点,自动将组件打包成独立的 chunk 文件,当访问对应路由时才会加载。 - 生成的文件:构建后会在
dist/js目录下生成类似chunk-abc123.js的文件。
2. 自定义 Chunk 名称(Webpack 魔法注释)
通过 Webpack 的魔法注释(Magic Comments)指定生成的 chunk 名称,便于调试和预加载:
component: () => import(/* webpackChunkName: "home" */ './views/Home.vue')
- 效果:生成的 chunk 文件会被命名为
home.[hash].js。 - 注意:需确保 Webpack 配置中允许使用魔法注释(默认支持)。
3. 兼容 Babel 配置
如果项目使用 Babel,需确保安装了 @babel/plugin-syntax-dynamic-import 插件以支持动态 import 语法:
npm install --save-dev @babel/plugin-syntax-dynamic-import
在 babel.config.js 中添加插件:
module.exports = {
plugins: ['@babel/plugin-syntax-dynamic-import'],
};
4. Vue 3 的 defineAsyncComponent(可选)
如果需要更精细控制异步加载行为(如加载状态、错误处理),可以使用 defineAsyncComponent:
import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
);
// 在路由中使用
const routes = [
{
path: '/async',
component: AsyncComponent,
},
];
5. 旧版 Vue/Webpack 的 require.ensure(不推荐)
在 Webpack 2 及以下版本中,可以使用 require.ensure(已逐渐被动态 import 替代):
component: (resolve) => {
require.ensure([], () => {
resolve(require('./views/Home.vue'));
}, 'home'); // 'home' 是 chunk 名称
}
验证懒加载是否生效
- 构建产物检查:运行
npm run build后,检查dist/js目录是否有多个 chunk 文件。 - 浏览器 Network 面板:访问不同路由时,观察是否有新的 JS 文件被加载。
注意事项
- 预加载:结合
<link rel="prefetch">提前加载低优先级路由(Webpack 4+ 默认对异步 chunk 启用 prefetch)。 - 避免过度拆分:过多的小 chunk 文件可能影响缓存效率和 HTTP/2 性能,需合理平衡。
通过路由懒加载,可以显著优化大型应用的性能!
17、 如果让你从零开始写一个vue路由,说说你的思路
为了方便后期维护,建议独立出一个 router.js 文件
npm install vue-router
引入注册
import Router from 'vue-router';
Vue.user(Router);
向外暴露出一个router实例
export default new Router({
mode: '',
path: '',
name: '',
...
});
18、 说说vue-router完整的导航解析流程是什么?
1.导航被触发;2.在失活的组件里调用beforeRouteLeave守卫;3.调用全局beforeEach守卫;4.在复用组件里调用beforeRouteUpdate守卫;5.调用路由配置里的beforeEnter守卫;6.解析异步路由组件;7.在被激活的组件里调用beforeRouteEnter守卫;8.调用全局beforeResolve守卫;9.导航被确认;10..调用全局的afterEach钩子;11.DOM更新;12.用创建好的实例调用beforeRouteEnter守卫中传给next的回调函数。
Vue Router 的导航解析流程是一个完整且有序的链式过程,包含多个导航守卫的执行和数据流转。以下是完整的导航解析流程(按执行顺序排列):
1. 导航触发
通过以下方式触发导航:
- 点击
<router-link> - 调用
router.push()/router.replace()/router.go()
2. 调用离开守卫(组件级)
beforeRouteLeave
当前组件(即将离开的组件)的离开守卫。
典型用途:表单未保存提示、清理定时器。// 在组件内定义 beforeRouteLeave(to, from, next) { if (this.isFormDirty) { const confirmLeave = confirm('数据未保存,确认离开?'); next(confirmLeave); // next(false) 取消导航 } else { next(); // 继续导航 } }
3. 全局前置守卫
router.beforeEach()
全局路由前置守卫,在每次导航前调用。
典型用途:权限验证、登录检查。router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !isLoggedIn()) { next('/login'); // 重定向到登录页 } else { next(); // 继续导航 } });
4. 调用组件复用守卫(组件级)
beforeRouteUpdate
当路由变化但组件被复用时触发(如动态参数/user/:id变化)。
典型用途:更新动态参数对应的数据。beforeRouteUpdate(to, from, next) { this.userId = to.params.id; this.loadUserData(); next(); }
5. 路由独享守卫
beforeEnter
在路由配置中定义的路由独享守卫。
典型用途:特定路由的访问控制。const routes = [ { path: '/admin', component: Admin, beforeEnter: (to, from, next) => { if (!isAdmin()) next('/403'); // 权限不足跳转 else next(); } } ];
6. 解析异步组件
加载目标路由对应的异步组件(如懒加载的组件)。
component: () => import('./Admin.vue') // 动态导入组件
7. 调用进入守卫(组件级)
beforeRouteEnter
目标组件(即将进入的组件)的进入守卫。
关键特性:此时组件实例尚未创建,无法访问this。
典型用途:预取数据。beforeRouteEnter(to, from, next) { // 通过回调访问组件实例 next(vm => { vm.fetchData(to.params.id); // vm 是组件实例 }); }
8. 全局解析守卫
router.beforeResolve()
全局守卫,在所有组件守卫和异步组件解析完成后调用。
典型用途:最终确认导航(如数据预加载)。router.beforeResolve((to, from, next) => { if (to.meta.requiresData) preloadData().then(next); else next(); });
9. 确认导航
所有守卫通过后,导航被确认,触发以下操作:
- 更新 URL(History API 操作)
- 销毁旧组件(若不再复用)
- 创建新组件实例
10. 全局后置钩子
router.afterEach()
导航完成后触发,无法修改导航。
典型用途:埋点统计、页面滚动复位。router.afterEach((to, from) => { logPageView(to.path); // 记录页面访问 window.scrollTo(0, 0); // 滚动到顶部 });
11. 更新 DOM
渲染目标组件,完成视图更新。
12. 执行 beforeRouteEnter 的 next 回调
此时组件已创建,可通过回调访问组件实例:
beforeRouteEnter(to, from, next) {
next(vm => {
vm.initData(); // 安全操作组件实例
});
}
导航中断场景
在上述任何守卫中调用以下方法会中断导航:
next(false):取消导航,恢复原 URLnext('/login'):重定向到新路径throw Error:导航终止并触发错误
流程图解
触发导航 → 调用离开守卫 → 全局前置守卫 → 组件复用守卫 → 路由独享守卫 →
解析异步组件 → 进入守卫 → 全局解析守卫 → 确认导航 →
更新 DOM → 全局后置钩子 → 执行进入守卫回调
通过理解这一流程,可以精准控制路由行为(如权限、数据预加载),确保应用逻辑的可靠性!
19、 路由之间是怎么跳转的?有哪些方式?
this.$router.push/replace/go/resolve router-link to
20、 如果vue-router使用history模式,部署时要注意什么?
服务器的404页面需要重定向到index.html
21、 route和router有什么区别?
route代表当前路由对象,router代表整个vue实例下的路由对象,即router是new vueRouter的实例
22、 vue-router钩子函数有哪些?都有哪些参数?
全局的:beforeEach、beforeResolve、afterEach 路由的:beforeEnter 组件的:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave 参数:to、from、next;正对不同的钩子函数参数有所差异。
23、 vue-router是用来做什么的?它有哪些组件?
vue-router路由,通俗来讲主要是来实现页面的跳转,通过设置不同的path,向服务器发送的不同的请求,获取不同的资源。 主要组件:router-view、router-link