Skip to content

四、路由

1. Vue-Router 的懒加载如何实现

Vue Router 的 懒加载(Lazy Loading)是指 按需加载路由组件,即当访问某个路由时,才会加载对应的组件,而不是一次性加载所有组件。这样可以减少首屏加载时间,提升性能。


1. 为什么需要懒加载?

在单页面应用(SPA)中,如果所有路由组件都一次性加载,会导致:

  • 首屏加载变慢:JS 体积大,影响用户体验。
  • 资源浪费:用户可能不会访问某些页面,但它们仍然被加载。

懒加载 只在需要时才加载组件,优化了加载速度。


2. Vue Router 懒加载的实现

✅ 方法 1:import() 进行动态导入

Vue 3 默认支持 动态 import() 语法,可直接在 Vue Router 中使用:

js
import { createRouter, createWebHistory } from "vue-router";

const routes = [
  {
    path: "/home",
    component: () => import("@/views/Home.vue") // 懒加载
  },
  {
    path: "/about",
    component: () => import("@/views/About.vue") // 懒加载
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

📌 () => import("xxx") 语法

  • 只有当用户访问 /home 时,Home.vue 才会被加载。
  • Vue 自动将不同路由打包成独立的 chunk.js 文件

📌 Webpack 打包后的文件

sh
dist/
  ├── index.html
  ├── assets/
  ├── js/
   ├── app.js
   ├── 0.chunk.js  # Home.vue(按需加载)
   ├── 1.chunk.js  # About.vue(按需加载)

✅ 方法 2:使用 defineAsyncComponent()

Vue 3 提供了 defineAsyncComponent() 进行手动懒加载

js
import { defineAsyncComponent } from "vue";

const AsyncHome = defineAsyncComponent(() => import("@/views/Home.vue"));

const routes = [
  {
    path: "/home",
    component: AsyncHome
  }
];

📌 适用于

  • 需要显示 加载状态错误处理 时。

✅ 方法 3:带 loadingerror 处理

可以使用 defineAsyncComponent() 设置 加载中加载失败 状态:

js
import { defineAsyncComponent } from "vue";

const AsyncHome = defineAsyncComponent({
  loader: () => import("@/views/Home.vue"),
  loadingComponent: () => import("@/components/Loading.vue"), // 加载中组件
  errorComponent: () => import("@/components/Error.vue"), // 错误组件
  delay: 200, // 延迟 200ms 显示 loading
  timeout: 3000 // 3s 内未加载完成则报错
});

const routes = [
  { path: "/home", component: AsyncHome }
];

📌 适用于

  • 网络较慢时,显示 loading,提高用户体验。
  • 失败时,提供 错误提示

3. 懒加载结合 Webpack 分包

Webpack 按需打包,默认会把 import() 语法转换成独立的 chunk.js 文件

js
const routes = [
  {
    path: "/home",
    component: () => import(/* webpackChunkName: "home" */ "@/views/Home.vue")
  }
];

📌 webpackChunkName

  • 指定 chunk 名称,打包后变成 home.chunk.js,便于管理。
  • 默认名称是数字(如 0.chunk.js),加 webpackChunkName 可改为 home.chunk.js

4. Vue-Router 懒加载 vs 非懒加载

对比项懒加载非懒加载
加载时机访问页面时加载进入网站时一次性加载
首屏加载,只加载必要代码,加载所有组件
适用场景大项目,页面较多小项目,页面少
网络请求访问不同页面触发请求只请求一次

🚀 结论

  • 推荐懒加载,减少首屏加载时间。
  • 小项目(1-2 页) 可使用非懒加载import xxx from "...")。

5. 进阶:路由懒加载 + KeepAlive

Vue 3 结合 keep-alive 缓存组件,避免重复加载:

vue
<template>
  <keep-alive>
    <router-view v-slot="{ Component }">
      <component :is="Component" />
    </router-view>
  </keep-alive>
</template>

📌 优点

  • 懒加载减少首屏压力
  • keep-alive 避免页面切换时重新加载组件,提升体验。

6. 结论

懒加载方式适用场景实现方式
import() 动态加载最常用,默认方式() => import("@/views/Home.vue")
defineAsyncComponent()异步加载组件defineAsyncComponent(() => import("xxx"))
带 loading 和 error 处理网络慢或失败时defineAsyncComponent({ loader, loadingComponent, errorComponent })
webpackChunkName自定义打包文件名/* webpackChunkName: "home" */
keep-alive + 懒加载避免重复加载<keep-alive><router-view/></keep-alive>

🚀 推荐做法

  1. 所有路由组件使用懒加载 import()
  2. 列表页 + 详情页结合 keep-alive
  3. 网络慢时,使用 loadingComponent 提示

合理使用懒加载,可显著优化 Vue 3 应用性能!🚀

2. 路由的hash和history模式的区别

Vue Router 提供了两种主要的路由模式:

  1. hash 模式(默认模式)
  2. history 模式

这两种模式的主要区别在于URL 结构、工作原理、兼容性、SEO 以及刷新行为


1. hash 模式

URL 结构

sh
http://example.com/#/home

📌 特点

  • # 后面的部分不会被发送到服务器,浏览器不会刷新页面。
  • 主要依赖 window.onhashchange 监听 # 变化,实现前端路由。

hash 模式的原理

  • window.location.hash 代表 # 后面的路径部分。
  • Vue 监听 hashchange 事件,实现路由切换:
js
window.addEventListener("hashchange", () => {
  console.log("Hash 变化:", window.location.hash);
});
  • 服务器不会接管 # 之后的部分,所以刷新页面不会 404。

hash 模式的优缺点

优点

  • 兼容性好(所有浏览器都支持 hash)。
  • 无需服务器配置,直接可用。
  • 刷新不会 404,因为 # 后的内容不会被发送到服务器。

缺点

  • URL 结构不美观,带有 #
  • 影响 SEO,搜索引擎不识别 # 之后的内容(除非 SSR)。

hash 模式示例

js
import { createRouter, createWebHashHistory } from "vue-router";

const router = createRouter({
  history: createWebHashHistory(), // 使用 hash 模式
  routes: [
    { path: "/home", component: Home },
    { path: "/about", component: About }
  ]
});

📌 最终的 URL

sh
http://example.com/#/home

2. history 模式

URL 结构

sh
http://example.com/home

📌 特点

  • 采用 HTML5 History APIpushState()replaceState())。
  • 没有 #,URL 结构更美观
  • 依赖 服务器端支持,否则刷新会 404。

history 模式的原理

  • Vue Router 使用 history.pushState() 修改浏览器地址:
js
history.pushState(null, "", "/home");
  • 监听 popstate 事件,实现路由跳转:
js
window.addEventListener("popstate", () => {
  console.log("History 变化:", window.location.pathname);
});
  • 服务器端需要配置 fallback 规则,否则刷新会 404

history 模式的优缺点

优点

  • URL 结构清晰,没有 #,更符合 RESTful 规范
  • 更好的 SEO,搜索引擎可以识别完整路径(适用于 SSR)。
  • 用户体验更好,类似原生网站的导航方式。

缺点

  • 需要服务器端配置,否则刷新时会 404。
  • 不支持 IE9 及以下版本(不支持 pushState)。

history 模式示例

js
import { createRouter, createWebHistory } from "vue-router";

const router = createRouter({
  history: createWebHistory(), // 使用 history 模式
  routes: [
    { path: "/home", component: Home },
    { path: "/about", component: About }
  ]
});

📌 最终的 URL

sh
http://example.com/home

3. history 模式如何避免刷新 404

由于 history 模式去掉了 #,当用户直接访问 http://example.com/home,服务器会尝试返回 home 这个文件,如果不存在,则返回 404。

✅ 解决方案:服务器配置重定向

  • Apache
apache
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>
  • Nginx
nginx
location / {
  try_files $uri /index.html;
}
  • Node.js Express
js
app.use((req, res, next) => {
  res.sendFile(path.resolve(__dirname, "dist/index.html"));
});

📌 作用

  • 所有路由请求都重定向到 index.html,然后 Vue Router 再解析路由。

4. hash vs history 对比

对比项hash 模式history 模式
URL 结构http://example.com/#/homehttp://example.com/home
实现方式window.onhashchange 监听 # 变化history.pushState()
刷新 404❌ 不会 404✅ 需要服务器配置
兼容性✅ 所有浏览器支持❌ IE9 及以下不支持
SEO 友好性❌ 不支持✅ 适用于 SSR
使用场景适用于无需服务器配置的小项目适用于SEO 友好的大项目

5. 什么时候选择 hash 模式 or history 模式?

hash 模式适用于:

  • 小型项目,无需服务器配置。
  • 不需要 SEO,如后台管理系统。
  • 兼容性要求高(支持老旧浏览器)

history 模式适用于:

  • SEO 需求高,如博客、企业官网(结合 SSR)。
  • 有服务器支持,可以配置 Nginx/Apache。
  • 更符合 RESTful 风格,用户体验更好

6. 结论

  • hash 模式简单易用,不需要服务器配置,但 URL 带 #,SEO 不友好。
  • history 模式 URL 更清晰,SEO 友好,但需要 服务器端配置 防止刷新 404。
  • 推荐:
    • 后台管理系统(如 Vue Admin):hash 模式
    • 官网 / 商城 / 需 SEO 页面(如 Vue SSR):history 模式(结合 Nuxt.js)

🚀 Vue Router 默认使用 hash 模式,如有 SEO 需求,建议使用 history 模式并配置服务器支持!

3. $route 和$router 的区别

在 Vue Router 中,$route$router 都是路由对象,但它们的作用不同:

对比项$route$router
作用存储当前路由的信息(路径、参数等)负责路由导航(跳转、前进、后退)
数据类型是一个对象(只读)是一个Vue Router 实例(可操作)
是否可修改❌ 不能修改(只读)✅ 可用于编程式导航
典型用法获取 pathparamsquery执行 push()replace()go()
名称路由路由器

1. $route (路由)

$route 是一个对象,存储当前路由的信息,包括:

js
$route = {
  path: "/home", // 当前路径
  name: "home", // 路由名称
  params: {}, // 路由参数
  query: {}, // 查询参数
  fullPath: "/home?user=123", // 完整路径
  hash: "#section1", // 哈希值
  matched: [], // 匹配的路由记录
}

✅ 示例:获取当前路径

vue
<template>
  <div>当前路径: {{ $route.path }}</div>
</template>

📌 示例 URL

sh
http://example.com/home?user=123

📌 结果

sh
当前路径: /home

✅ 示例:获取 query 参数

vue
<template>
  <div>查询参数: {{ $route.query.user }}</div>
</template>

📌 结果

sh
查询参数: 123

2. $router (路由器)

$routerVue Router 的实例,提供路由控制方法:

方法作用
$router.push()跳转到新页面(可回退)
$router.replace()跳转但不保留历史记录
$router.go(n)前进 / 后退 n
$router.back()返回上一页
$router.forward()前进一页

✅ 示例:编程式导航

(1) push()(带参数跳转)
vue
<button @click="$router.push('/about')">跳转到 About</button>

📌 相当于

js
this.$router.push({ path: "/about" });

(2) push() 传递 params
js
this.$router.push({ name: "user", params: { id: 123 } });

📌 生成的 URL

sh
http://example.com/user/123

(3) push() 传递 query
js
this.$router.push({ path: "/home", query: { user: "Alice" } });

📌 生成的 URL

sh
http://example.com/home?user=Alice

(4) replace()(替换当前历史记录)
vue
<button @click="$router.replace('/dashboard')">跳转到 Dashboard</button>

📌 区别

  • push():会在浏览器历史记录中添加新记录(可回退)。
  • replace()替换当前页面,不会生成历史记录(无法回退)。

(5) go(n)(前进 / 后退 n 步)
vue
<button @click="$router.go(-1)">返回上一页</button>

📌 效果

  • this.$router.go(-1) 相当于 window.history.back()
  • this.$router.go(1) 相当于 window.history.forward()

3. $route vs $router 对比总结

对比项$route(当前路由信息)$router(路由控制)
作用获取当前路由信息执行导航操作
是否可修改❌ 只读✅ 可操作
典型用法this.$route.paththis.$route.querythis.$router.push()this.$router.go(-1)
使用场景显示路径、参数进行页面跳转

4. Vue 3 setup() 中如何使用?

Vue 3 取消了 this,可以用 useRoute()useRouter() 代替:

vue
<script setup>
import { useRoute, useRouter } from "vue-router";

const route = useRoute(); // 等价于 this.$route
const router = useRouter(); // 等价于 this.$router

// 获取当前路径
console.log(route.path);

// 跳转路由
const goToAbout = () => {
  router.push("/about");
};
</script>

5. 结论

  • $route(useRoute) 用于 获取路由信息,不能修改:
js
console.log($route.path); // "/home"
console.log($route.query); // { user: "Alice" }
  • $router(useRouter) 用于 跳转路由
js
this.$router.push("/about"); // 跳转到 About 页面
this.$router.replace("/dashboard"); // 替换当前页面
this.$router.go(-1); // 返回上一页

🚀 推荐

  • 获取路由信息useRoute()
  • 进行路由跳转useRouter()

掌握 $route$router,可以更好地管理 Vue Router!🚀

5. 如何定义动态路由?如何获取传过来的动态参数?

动态路由(Dynamic Routing)允许在路径中使用变量,从而创建可复用的路由。这对于详情页、用户页面、分类页面等非常有用。


1. 定义动态路由

在 Vue Router 中,动态路由参数使用 : 语法:

js
import { createRouter, createWebHistory } from "vue-router";
import User from "@/views/User.vue";

const routes = [
  { path: "/user/:id", component: User }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

📌 说明

  • :id 是一个动态参数,可以匹配 /user/123/user/456 等不同 URL。
  • User.vue 组件中,我们可以获取 id

2. 获取动态路由参数

✅ 方法 1:使用 $route.params

适用于 Vue 2 和 Vue 3(选项 API)

vue
<template>
  <div>
    <h2>用户 ID: {{ $route.params.id }}</h2>
  </div>
</template>

<script>
export default {
  mounted() {
    console.log("用户 ID:", this.$route.params.id);
  }
};
</script>

📌 示例 URL

http://example.com/user/123

📌 输出

用户 ID: 123

✅ 方法 2:使用 useRoute()(Vue 3 Composition API)

vue
<template>
  <div>
    <h2>用户 ID: {{ route.params.id }}</h2>
  </div>
</template>

<script setup>
import { useRoute } from "vue-router";

const route = useRoute();
console.log("用户 ID:", route.params.id);
</script>

📌 Vue 3 推荐使用 useRoute() 代替 this.$route


3. 动态路由传递多个参数

可以在路径中添加多个参数:

js
{ path: "/user/:id/:name", component: User }

📌 示例 URL

http://example.com/user/123/Alice

📌 获取参数

vue
<template>
  <div>
    <h2>用户 ID: {{ $route.params.id }}</h2>
    <h2>用户名: {{ $route.params.name }}</h2>
  </div>
</template>

📌 输出

用户 ID: 123
用户名: Alice

4. 使用 props 传递动态参数

默认情况下,$route.params 只能在 this.$route 中访问。Vue 允许将 动态参数作为 props 传递给组件,让组件更加解耦:

js
{ path: "/user/:id", component: User, props: true }

📌 组件内直接接收 props

vue
<template>
  <h2>用户 ID: {{ id }}</h2>
</template>

<script setup>
defineProps(["id"]);
</script>

📌 优点

  • 组件更加清晰,无需访问 $route.params
  • 更易测试和复用。

5. 编程式跳转(动态参数)

✅ 使用 $router.push()

vue
<button @click="$router.push('/user/456')">跳转到用户 456</button>

📌 等价于

js
this.$router.push({ path: `/user/456` });

✅ 传递参数

js
this.$router.push({ name: "user", params: { id: 789 } });

📌 注意

  • name 必须匹配 routes 里的 name
js
{ path: "/user/:id", name: "user", component: User }
  • 避免使用 path + params 一起使用
js
this.$router.push({ path: "/user", params: { id: 789 } }); // ❌ 无效

✅ 正确写法

js
this.$router.push({ name: "user", params: { id: 789 } });

6. 监听动态参数变化

watch() 监听 params 变化

id 变化时,执行逻辑:

vue
<script setup>
import { useRoute, watch } from "vue-router";

const route = useRoute();

watch(
  () => route.params.id,
  (newId, oldId) => {
    console.log("用户 ID 变化:", oldId, "->", newId);
  }
);
</script>

📌 Vue 3 推荐 watch() 监听 route.params.id,避免重新加载组件。


7. 匹配可选参数

如果 :id 不是必须的,可以使用 ?

js
{ path: "/user/:id?", component: User }

📌 示例 URL

http://example.com/user      ✅ 允许
http://example.com/user/123  ✅ 允许

📌 获取参数

js
console.log(this.$route.params.id); // 可能是 undefined

8. 404 匹配(通配符 *

如果用户访问了未定义的路由,可以使用通配符 /:pathMatch(.*)*

js
{ path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound }

📌 示例

http://example.com/unknown  -> 渲染 NotFound 组件

9. redirect(重定向动态路由)

如果用户访问 /profile/:id,想让其重定向/user/:id

js
{ path: "/profile/:id", redirect: "/user/:id" }

📌 支持函数

js
{
  path: "/profile/:id",
  redirect: (to) => {
    return `/user/${to.params.id}`;
  }
}

10. 结论

功能实现方式
定义动态路由{ path: "/user/:id" }
获取参数(Vue 2)this.$route.params.id
获取参数(Vue 3)const route = useRoute(); route.params.id
监听参数变化watch(() => route.params.id, callback)
编程式导航this.$router.push({ name: "user", params: { id: 123 } })
通配符 404{ path: "/:pathMatch(.*)*", component: NotFound }

🚀 推荐

  • Vue 3 组件内获取参数useRoute()
  • 避免 path + params 组合使用 name + params
  • 监听参数变化watch()

动态路由让 Vue Router 更灵活,适用于详情页、用户中心、搜索结果等场景!🚀

6. Vue-Router 路由钩子在生命周期的体现

Vue Router 提供了全局、组件内、单个路由独享的导航守卫(钩子),用于在路由切换前后执行逻辑,如:

  • 权限验证(登录检查)
  • 页面数据预加载
  • 取消请求
  • 切换动画

Vue 组件的生命周期与 Vue Router 的路由钩子(导航守卫) 关系密切,特别是在路由切换时,导航守卫会影响组件的 创建、挂载、更新和销毁


1. Vue Router 路由钩子(导航守卫)

Vue Router 主要有三类路由钩子:

类别钩子函数作用
全局守卫beforeEachbeforeResolveafterEach作用于所有路由
路由独享守卫beforeEnter作用于单个路由
组件内守卫beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave作用于组件内

2. 全局守卫的生命周期

(1) beforeEach(进入路由前)

  • 路由跳转前执行,可以用于 权限校验判断是否登录
  • 不会影响组件生命周期,因为此时组件还未创建。
js
router.beforeEach((to, from, next) => {
  console.log("全局 beforeEach:", from.path, "->", to.path);
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next("/login"); // 未登录,重定向到登录页
  } else {
    next(); // 允许通过
  }
});

📌 示例

  • 访问 /admin 时,检查 meta.requiresAuth,未登录则跳转 /login

(2) beforeResolve(异步请求前)

  • 路由切换后组件渲染前 触发,适用于 获取异步数据(如 API 请求)。
  • 组件未创建,无法访问 this
js
router.beforeResolve(async (to, from, next) => {
  console.log("全局 beforeResolve:", to.path);
  await fetchData(); // 预加载数据
  next();
});

📌 适用于

  • beforeResolve 里调用 await fetchData()确保页面加载前数据就绪

(3) afterEach(路由切换完成)

  • 路由切换后 触发,适用于统计埋点修改标题
  • 不会影响组件生命周期,不会阻止导航。
js
router.afterEach((to) => {
  console.log("全局 afterEach:", to.path);
  document.title = to.meta.title || "默认标题";
});

📌 适用于

  • 记录访问日志,比如 Google Analytics。
  • 动态修改页面标题document.title = to.meta.title)。

3. 单个路由独享 beforeEnter

  • 只作用于当前路由,组件还未创建。
  • 用于单个页面权限校验,比如限制 /admin 访问
js
const routes = [
  {
    path: "/admin",
    component: Admin,
    beforeEnter: (to, from, next) => {
      console.log("路由独享 beforeEnter:", to.path);
      if (!isAdmin()) {
        next("/403"); // 权限不足,跳转 403
      } else {
        next();
      }
    }
  }
];

📌 适用于

  • 限制管理员访问 /admin,非管理员跳转 /403

4. 组件内守卫的生命周期

组件的 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave 直接影响组件的创建、更新和销毁

钩子函数触发时机能否访问 this(组件实例)
beforeRouteEnter进入前,组件未创建❌(需 next(vm => vm.xxx)
beforeRouteUpdate复用组件时(参数变化)
beforeRouteLeave离开前

(1) beforeRouteEnter(进入组件前)

  • 组件未创建,无法访问 this
  • 适用于异步数据预加载,比如 进入详情页前请求数据
vue
<script setup>
import { onBeforeRouteEnter } from "vue-router";

onBeforeRouteEnter((to, from, next) => {
  console.log("组件 beforeRouteEnter:", to.path);
  fetchData().then(() => next());
});
</script>

📌 注意

  • this 还不可用,可以用 next(vm => vm.xxx) 访问组件实例:
js
beforeRouteEnter(to, from, next) {
  next(vm => {
    console.log("可以访问 this:", vm);
  });
}

(2) beforeRouteUpdate(复用组件时)

  • 当参数变化时(如 /user/1/user/2),组件不重新创建,而是复用**,此时会触发 beforeRouteUpdate**。
  • 适用于监听 id 变化,并重新请求数据
vue
<script setup>
import { onBeforeRouteUpdate } from "vue-router";

onBeforeRouteUpdate((to, from) => {
  console.log("组件 beforeRouteUpdate:", to.path);
  fetchUserData(to.params.id);
});
</script>

📌 适用于

  • /user/:id/user/:id 切换时,组件不销毁,手动加载新用户数据。

(3) beforeRouteLeave(离开组件前)

  • 适用于:离开页面时,提示未保存数据,或取消定时器
vue
<script setup>
import { onBeforeRouteLeave } from "vue-router";

onBeforeRouteLeave((to, from, next) => {
  if (!confirm("确定要离开吗?未保存数据将丢失")) {
    next(false); // 取消导航
  } else {
    next();
  }
});
</script>

📌 适用于

  • 表单编辑页,用户离开前给出提示。
  • 清理定时器、WebSocket 连接

5. Vue Router 钩子和组件生命周期的关系

完整执行顺序(进入新页面)

sh
beforeEach beforeEnter beforeRouteEnter created beforeMount mounted afterEach beforeResolve

完整执行顺序(离开页面)

sh
beforeRouteLeave beforeEach beforeEnter beforeRouteEnter destroyed beforeUnmount

📌 关键点

  • beforeEach 先执行,组件还未创建。
  • beforeRouteEnter created 早执行,但不能访问 this
  • beforeRouteLeave destroyed 早执行,可用于清理数据

6. 结论

钩子类型触发时机适用场景
beforeEach全局路由跳转前登录权限校验
beforeResolve解析路由前预加载数据
afterEach路由跳转后记录访问日志
beforeEnter进入某个路由前限制访问(单个页面)
beforeRouteEnter组件创建前预加载数据(不能用 this
beforeRouteUpdate组件参数更新监听动态参数
beforeRouteLeave组件离开前提示保存表单数据

7. Vue-router跳转和location.href有什么区别

在 Vue 应用中,路由跳转有两种常见方式:

  1. Vue Router 方式$router.push() / useRouter().push()
  2. 原生跳转window.location.href

它们的核心区别在于页面刷新、SPA 体验、历史记录管理和参数传递


1. Vue Router 跳转

✅ 使用 push()

js
this.$router.push("/home");  // Vue 2
js
import { useRouter } from "vue-router";
const router = useRouter();
router.push("/home");  // Vue 3

✅ 使用 replace()

js
this.$router.replace("/dashboard");

📌 区别

  • push()添加新历史记录(可以回退)
  • replace()替换当前历史记录(不能回退)

✅ 传递参数

1️⃣ query 传参
js
this.$router.push({ path: "/home", query: { user: "Alice" } });

📌 最终 URL

http://example.com/home?user=Alice
2️⃣ params 传参
js
this.$router.push({ name: "user", params: { id: 123 } });

📌 最终 URL

http://example.com/user/123

⚠️ 注意

  • params 不能和 path 一起使用,必须用 name
js
this.$router.push({ path: "/user", params: { id: 123 } }); // ❌ 无效

正确写法

js
this.$router.push({ name: "user", params: { id: 123 } });

2. window.location.href 跳转

js
window.location.href = "/home";

📌 特点

  • 会刷新页面,重新加载所有资源(HTML、CSS、JS)。
  • 不受 Vue Router 控制,不影响 Vue 组件状态。
  • 适用于跳转外部链接,如:
js
window.location.href = "https://google.com";
  • 不能传 params,只能用 query
js
window.location.href = "/home?user=Alice"; // 只能手动拼接 URL

3. 核心区别对比

对比项Vue Router($router.pushwindow.location.href(原生跳转)
页面刷新不会刷新(SPA 单页面体验)会刷新,重新加载资源
历史记录保留历史记录(可回退)覆盖历史(回退失效)
参数传递params / query 传参❌ 只能手动拼接 query
跨域跳转❌ 只能跳转 Vue 内部路由可跳转外部网站
适用场景🔹 Vue 内部页面切换🔹 外部链接、强制刷新
SEO 友好❌ 需要 history 模式✅ 适用于 SSR 页面

4. 什么时候用 Vue Router?什么时候用 location.href

$router.push() 适用于

  • SPA 内部跳转(Vue 组件切换,不刷新页面)。
  • 动态参数传递paramsquery)。
  • 路由权限控制beforeEach() 守卫)。

window.location.href 适用于

  • 跳转外部网站(如 https://google.com)。
  • 强制刷新当前页面(如 /dashboard?refresh=1)。
  • 非 Vue 管理的页面(如 iframe 内部跳转)。

5. location.href 强制刷新 Vue 页面

有时候,我们需要在 Vue 内部强制刷新页面:

js
window.location.reload();  // 重新加载当前页面

📌 适用于

  • 清空 Vue 状态,回到初始状态。

6. 结论

功能Vue Routerwindow.location.href
页面刷新❌ 不刷新(SPA 单页面)✅ 刷新(重新加载资源)
SEO 友好❌ 需要 history 模式✅ 适用于 SSR
参数传递params / query❌ 只能手动拼接 query
适用场景Vue 内部路由切换外部跳转 / 强制刷新

🚀 最佳实践

  • Vue 内部跳转this.$router.push()
  • 外部跳转window.location.href
  • 强制刷新window.location.reload()

8. params和query的区别

在 Vue Router 中,paramsquery 都用于传递路由参数,但它们的用法、URL 结构、获取方式有所不同。


1. params(路径参数)

特点

  • 直接嵌入 URL 路径,不带 ?
  • 必须在 path 定义时使用 :param
  • 不支持 push({ path: ... }),必须用 name
  • 刷新后仍然存在(因为它是路径的一部分)。

params 传参示例

📌 1️⃣ 定义动态路由
js
const routes = [
  { path: "/user/:id", name: "user", component: User }
];

📌 2️⃣ 编程式导航
js
this.$router.push({ name: "user", params: { id: 123 } });

📌 最终 URL

http://example.com/user/123

📌 3️⃣ 获取 params 参数

Vue 2

vue
<template>
  <div>用户 ID: {{ $route.params.id }}</div>
</template>

Vue 3(Composition API)

vue
<script setup>
import { useRoute } from "vue-router";
const route = useRoute();
console.log("用户 ID:", route.params.id);
</script>

📌 params 只能在 path 里定义的路由中使用


params 不能与 path 一起使用

js
this.$router.push({ path: "/user", params: { id: 123 } }); // ❌ 无效!

📌 正确写法

js
this.$router.push({ name: "user", params: { id: 123 } }); // ✅

params 适用场景

适用情况示例
用户详情页/user/:id/user/123
商品详情页/product/:id/product/456
层级路由/category/:categoryId/product/:productId

2. query(查询参数)

特点

  • 作为 URL 查询字符串,以 ?key=value 形式出现。
  • 无需在 routes 里定义,任何路径都可以携带 query
  • 可以与 path 一起使用
  • 刷新后仍然存在(因为它是 URL 的一部分)。

query 传参示例

📌 1️⃣ 编程式导航
js
this.$router.push({ path: "/home", query: { user: "Alice" } });

📌 最终 URL

http://example.com/home?user=Alice

📌 2️⃣ 获取 query 参数

Vue 2

vue
<template>
  <div>查询参数: {{ $route.query.user }}</div>
</template>

Vue 3(Composition API)

vue
<script setup>
import { useRoute } from "vue-router";
const route = useRoute();
console.log("查询参数:", route.query.user);
</script>

📌 query 适用于 搜索、筛选、分页等功能


query 适用场景

适用情况示例 URL
搜索功能/search?keyword=vue
筛选条件/products?category=electronics&price=low
分页/articles?page=2&limit=10

3. params vs query 总结

对比项params(路径参数)query(查询参数)
URL 形式/user/:id/user/123/home?user=Alice
定义方式必须在 routes 里定义任何路由都可用
是否可以直接修改❌ 不能手动修改 URL✅ 直接在浏览器地址栏修改
是否支持 path❌ 只能配合 name✅ 可以直接 push({ path })
刷新是否保留✅ 是(因为在路径中)✅ 是(因为在 URL 中)
适用场景详情页(用户 ID、商品 ID)搜索、筛选、分页

4. 什么时候用 params?什么时候用 query

params 适用于

  • 需要 唯一标识资源(如用户 ID、商品 ID)。
  • URL 层级结构清晰(如 /user/:id)。
  • 适合 RESTful 风格(API 端常用 /users/:id)。

query 适用于

  • 搜索、筛选、分页等可选参数
  • 需要支持动态参数(URL 手动输入)。
  • 多个参数组合(如 /search?keyword=vue&page=2)。

5. 结论

使用场景推荐方式示例
详情页(用户、商品等)params/user/123
搜索功能(keyword)query/search?keyword=vue
分页query/articles?page=2&limit=10
筛选(类别、价格等)query/products?category=books&price=low
导航不改变 URLparams/profile/:id

🚀 最佳实践

  • params 适用于层级路由(用户/商品详情)
  • query 适用于搜索、筛选、分页等非必要参数
  • RESTful API 推荐 params,灵活传参推荐 query

合理使用 paramsquery,优化 Vue 路由设计!🚀

9. 对前端路由的理解

前端路由(Frontend Routing)是指 在单页面应用(SPA)中使用 JavaScript 在不刷新页面的情况下更新 URL 并渲染不同的组件或页面


1. 前端路由的工作原理

在传统多页面应用(MPA,Multi-Page Application)中,每次页面跳转都会向服务器请求一个新的 HTML 文件,导致页面刷新。而在 前端路由 中:

  • 不会刷新页面
  • URL 变化时,前端动态更新视图
  • 减少服务器请求,提升用户体验
  • 通常使用 hashhistory API

📌 示例

  1. 访问 /home 时,显示 Home.vue
  2. 访问 /about 时,显示 About.vue
  3. 无需重新加载页面,仅仅是组件的切换

2. 前端路由的实现方式

hash 模式

原理:使用 window.location.hash 监听 # 变化,进行页面切换。

  • http://example.com/#/home
  • http://example.com/#/about

实现方式

js
window.addEventListener("hashchange", () => {
  console.log("当前 hash:", window.location.hash);
});

📌 特点

  • URL 带 #,不美观
  • 不会发送请求到服务器
  • 兼容性好(所有浏览器支持)

history 模式

原理:使用 pushState() / replaceState() 修改 URL,同时监听 popstate 事件进行页面切换。

  • http://example.com/home
  • http://example.com/about

实现方式

js
window.history.pushState({}, "", "/home");
window.addEventListener("popstate", () => {
  console.log("当前路径:", window.location.pathname);
});

📌 特点

  • URL 没有 #,更符合 RESTful 规范
  • 需要服务器支持,否则刷新 404
  • SEO 友好,适合 SSR

3. Vue Router 处理前端路由

Vue 提供了 Vue Router 进行前端路由管理。

js
import { createRouter, createWebHistory } from "vue-router";
import Home from "@/views/Home.vue";
import About from "@/views/About.vue";

const router = createRouter({
  history: createWebHistory(), // history 模式
  routes: [
    { path: "/home", component: Home },
    { path: "/about", component: About }
  ]
});

export default router;

📌 Vue Router 让前端路由管理更简单,支持 hashhistory 模式。


4. 前端路由的核心功能

功能描述示例
动态路由使用 :id 定义动态路径/user/:id
编程式导航push() 进行跳转$router.push('/home')
路由守卫beforeEach() 进行权限校验next('/login')
嵌套路由组件内部嵌套子路由/user/:id/profile
懒加载组件按需加载,提升性能() => import('@/views/Home.vue')

5. 前端路由 vs 后端路由

对比项前端路由(SPA)后端路由(MPA)
页面刷新❌ 不刷新页面✅ 每次跳转刷新
请求方式仅请求 API 数据服务器返回整个 HTML
加载速度首屏慢,后续快每次跳转都慢
SEO 友好❌ 需要 SSR✅ 天然支持
适用场景后台管理、Web App官网、博客

6. 什么时候选择前端路由?什么时候选择后端路由?

前端路由适合

  • 后台管理系统(Admin)
  • 在线应用(如 Vue 应用)
  • 移动端 Web App

后端路由适合

  • SEO 需求高的站点(如博客、企业官网)
  • 静态页面(如文档、内容站)

🚀 推荐

  • SEO 需求高 → Nuxt.js(Vue SSR)
  • 后台管理 → Vue Router(SPA)
  • 大型项目 → 结合前后端路由(如 SSR + API)

7. 结论

前端路由优点前端路由缺点
✅ 页面切换快,用户体验好❌ 需要服务端支持 history
✅ 服务器压力小,减少请求❌ 首屏加载较慢(需优化)
✅ 支持动态加载组件❌ SEO 不友好(除 SSR 外)

🚀 Vue Router 是前端路由的最佳实践,结合 history + keep-alive 可以大幅提升性能! 🚀

评论区

欢迎留言、补充或勘误。

xiaoba.blog