文章目录
vue-router 是什么?它的作用是什么?
是Vue.js官方提供的一个插件,用于实现前端路由功能。
是SPA(单页应用)的路径管理器,使得用户在浏览器中切换页面时,不需要重新加载整个页面,而只是更新部分内容,从而提供更流畅的用户体验。
主要作用包括:
-
路由映射: 可以通过定义路由规则来将不同的URL路径映射到相应的组件上。当用户访问特定的URL时,Vue Router会根据路由规则选择并加载对应的组件。
-
嵌套路由: 在一个组件中定义子路由,从而实现更复杂的页面结构。这样可以方便管理和组织你的页面结构,提高代码复用性。
-
路由传参: 通过URL路径、查询参数或者路由配置中的属性进行传递。这样可以方便地实现动态路由和组件间的数据传递。
-
导航守卫: Vue Router提供了多种导航守卫(Navigation Guards)的机制,用于在路由导航过程中进行拦截和控制。你可以使用导航守卫来验证用户的登录状态、权限验证、页面切换动画等。
在Vue中使用Vue Router
安装Vue Router:
npm install vue-router --save
创建路由实例:
src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 创建 router 实例
const router = new VueRouter({
routes: [
// 在这里定义你的路由规则
]
})
export default router
设置路由规则:
每个路由规则都包含一个路径(path)和对应的组件(component):
import Home from '../view/home/Home.vue';
const About = { template: '<div>about</div>' }
const router = new VueRouter({
routes: [
{
path: '/',
// "component" 可以是:
// 1. 通过 `Vue.extend()` 创建的组件构造器
// 2. 组件配置对象
// 3. vue组件
component: Home // 在这里替换成你的首页组件
},
{
path: '/about',
component: About // 在这里替换成你的关于页面组件
},
// 添加更多的路由规则...
]
})
挂载到Vue实例中:
import Vue from 'vue'
import router from './router' // 引入上述创建的路由实例
new Vue({
router, // 配置路由实例
// 其他配置项...
}).$mount('#app')
在模板中使用路由:
在你的Vue组件的模板中,使用<router-link>
组件来生成路由链接,使用<router-view>
组件来展示对应的组件内容。示例代码如下:
<template>
<div>
<!-- router-link 声明式导航跳转 -->
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<!-- 添加更多的路由链接... -->
<!-- router-view 路由出口:路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
computed: {
username() {
// 在任何组件内通过 `this.$route` 访问当前路由
// 我们很快就会看到 `params` 是什么
return this.$route.params.username;
},
},
methods: {
goBack() {
// 在任何组件内通过 `this.$router` 访问路由实例
window.history.length > 1
? this.$router.go(-1)
: this.$router.push("/");
},
},
};
</script>
核心组件是哪些?
RouterView:路由视图,<router-view>
标签,用于显示匹配到的路由组件内容的占位符组件。
RouterLink:<router-link>
标签,用于创建到指定路由的超链接组件。当点击时会改变URL并进行导航,而不是进行全页刷新
-
结合RouterLinkActive:常用于为激活的导航链接添加样式
-
当前激活的路由链接会添加一个特定的类名
router-link-active
-
可通过
active-class
来修改默认的router-link-active
类名<router-link to="/some-route" active-class="custom-active-class">Some Route</router-link>
-
router 和 route 的区别
router:Vue Router的主要实例,用于管理路由规则和导航。因此你可以调用 this.$router.push
**
route:路由记录对象,表示当前激活的路由状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的路由记录 (route records)。可以通过$route
属性访问当前路由对象的信息,如路由参数、查询参数等。
状态信息:
- fullpath
- path
- params
- query
- hash
- meta
导航守卫(NavigationGuard)
全局路由守卫
beforeEach
beforeEach(to, from, next)
:前置守卫
-
to :即将要进入的目标路由对象
-
from:当前正要离开的路由对象
-
next:路由控制参数
-
next()
:如果一切正常,则调用这个方法进入下一个钩子 -
next(false)
:取消导航(即路由不发生改变) -
next('/login')
:当前导航被中断,然后进行一个新的导航 -
next(error)
:如果一个 Error 实例,则导航会被终止且该错误会被传递给
-
作用:
-
鉴权验证(身份、登录、页面访问权限 等)
-
重定向
-
修改网页title
router.beforeEach((to, from) => { document.title = to.meta.title; });
-
监听错误 NavigationFailure:
-
导航失败的事件和相关信息:
- 错误消息:描述导航失败的原因。
- 错误代码:用于标识特定类型的导航错误。
- 原始错误对象:包含有关错误的更多详细信息。
-
示例:
router.beforeEach((to, from, next) => { try { // 尝试进行路由跳转 next(); } catch (error) { if (error instanceof NavigationFailure) { // 处理导航失败的情况 console.error('导航失败:', error.message); // 可以在这里执行其他操作,如显示错误消息给用户等 } else { // 处理其他类型的错误 console.error('发生未知错误:', error); } } });
-
afterEach
afterEach(to, from)
:后置守卫
作用:当前页面的记录日志(Sentry、LogRocket),并将信息发送到服务器进行分析用户行为
- Sentry:错误跟踪工具
- 错误监控:它能够实时监控应用程序的异常和错误日志,帮助开发者快速发现并解决问题。
- 多语言支持:Sentry支持多种编程语言和框架,这使得它可以在不同的开发环境中使用。
- 智能化分析:它提供智能化的错误分析,帮助开发者理解错误产生的原因,从而更有效地修复问题。
- 集成平台:作为一个集成平台,Sentry提供了丰富的功能和灵活的配置选项,以满足不同项目的需求。
- LogRocket:前端日志记录工具
- 前端日志记录:LogRocket专注于前端,帮助开发者记录用户在Web应用中的操作,如点击、页面浏览等。
- 用户行为分析:通过记录用户的交互行为,LogRocket可以辅助开发者了解用户如何使用应用,从而优化用户体验。
- 性能监控:除了记录错误和用户行为,LogRocket还可以监控应用的性能,如加载时间和运行时错误。
beforeResolve
beforeResolve
:路由解析
路由独享守卫:beforeEnter
beforeEnter(to, from, next)
:通常用于处理特定路由的需求,如加载数据、处理权限等
const router = new VueRouter({
routes: [
{
path: '/admin',
name: 'Admin'
component: () => import(/* webpackChunkName: "Admin" */ '../views/Admin.vue'),
beforeEnter: (to, from, next) => {
if (isLogin) {
return next()
}
return next('/login?redirect' = to.fullpath)
},
// beforeEnter: (route) => { }
}
]
})
组件内路由守卫
beforeRouteEnter
beforeRouteEnter(to, from, next)
:在导航确认前被调用
注意:
-
新组件还没被创建。所以不能获取实例(this)
-
可以通过传一个回调给
next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。beforeRouteEnter
是支持给next
传递回调的唯一守卫。对于beforeRouteUpdate
和beforeRouteLeave
来说,this 已经可用了,所以不支持传递回调,因为没有必要了。
export default {
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被确认前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next((vm) => {
// 通过 `vm` 访问组件实例
});
},
};
示例: 判断进入页面后的访问内容
export default {
data() {
return {
code: 1, // 步骤
};
},
beforeRouteEnter(to, from, next) {
// 从详情页进来
if (from.name == "detail") {
return next((vm) => {
vm.getDetail(2);
});
}
next();
},
methods: {
// 获取详情
getDetail(id) {
this.code = id;
},
},
};
beforeRouteUpdate
beforeRouteUpdate(to, from, next)
作用:常用于监听路由变化
export default {
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
this.name = to.params.name;
next();
},
};
beforeRouteLeave
beforeRouteLeave(to, from, next)
常用于:
- 禁止用户在还未保存修改前突然离开 / 离开页面前提示用户还有数据未保存
export default {
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
const answer = window.confirm(
"Do you really want to leave? you have unsaved changes!"
);
if (answer) {
next();
} else {
next(false); // 通过 `next(false)` 来取消路由跳转
}
},
};
完整的导航解析流程
-
点击导航被触发。
-
失活路由组件内触发
beforeRouteLeave
守卫。 -
触发 全局路由守卫
beforeEach
。 -
(判断):
-
在重用路由组件内触发
beforeRouteUpdate
守卫 (2.2+)。 -
在非重用路由配置中,触发路由独享守卫
beforeEnter
。-
解析异步路由组件。
-
在被激活的路由组件内触发
beforeRouteEnter
。 -
触发 全局路由守卫
beforeResolve
守卫 (2.5+)。 -
导航被确认。
-
触发 全局路由守卫
afterEach
。 -
触发 DOM 更新。
-
(判断)调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
-
-
编程导航(路由跳转)方式
Vue Router 的导航方法 (push、 replace、 go) 在各类路由模式 (history、 hash 和 abstract) 下表现一致
声明式:<router-link>
<router-link>
组件。
生成带有导航链接的可点击元素,默认会被渲染成一个 <a>
标签。
设置组件的 to
属性来指定目标路由路径,并可以使用其他属性来配置导航行为
当 <router-link>
对应的路由匹配成功,将自动设置 class 属性值 .router-link-active
<!-- 通过传入 `to` 属性指定目标路由路径。对应编程式的 `router.push` -->
<router-link to="/foo">Go to Foo</router-link>
<!-- 设置组件的 `replace` 属性。对应编程式的 router.replace -->
<router-link to="xx" replace>Go to Foo</router-link>
router.push
router.push(location[, onComponent, onAbort])
跳转指定地址,并添加到历史记录中。
会向 history 栈添加一个新的记录。所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
类似 window.history.pushState
声明式 | 编程式 |
---|---|
<router-link :to="..."> | router.push(...) |
参数:
-
location
要跳转的地址。可以是一个字符串路径,或者一个描述地址的对象// 字符串 router.push("detail"); router.push("/detail"); // 一个描述地址的对象 router.push({ name: "detail" }); // 命名的路由:/detail/12 router.push({ name: "detail", param: { id: "12" } }); // 注意:如果提供了 path,params 会被忽略 // 同样的规则也适用于 `router-link` 组件的 `to` 属性。 router.push({ path: '/detail', params: { id: '12' } }) // -> /detail // 带查询参数:/detail?id=12 router.push({ name: "detail", query: { id: "12" } });
可选参数:
-
onComponent
结束的回调 -
onAbort
取消的回调
在 2.2.0+,可选的在 router.push
或 router.replace
中提供 onComplete
和 onAbort
回调作为第二个和第三个参数。这些回调将会在导航成功完成 (在所有的异步钩子被解析之后) 或终止 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由) 的时候进行相应的调用。
在 3.1.0+,可以省略第二个和第三个参数,此时如果支持 Promise,router.push
或 router.replace
将返回一个 Promise。
router.replace
router.replace(location[, onComponent, onAbort])
用指定的路由替换当前路由。
跟 router.push
很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
类似 window.history.replaceState
声明式 | 编程式 |
---|---|
<router-link :to="..." replace> | router.replace(...) |
参数:
location
要跳转的地址。可以是一个字符串路径,或者一个描述地址的对象
可选参数:
-
onComponent
结束的回调 -
onAbort
取消的回调
router.go
router.go(n)
在历史记录中向前或向后移动 N 步。
类似 window.history.go(n)
参数:
-
没有参数: 前进一页,等价于
router.go(1)
-
n
整数,意思是在 history 记录中向前或者后退多少步- 0: 刷新当前页面
- 正整数: 前进几页
- 负整数: 后退几页
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1);
// 后退一步记录,等同于 history.back()
router.go(-1);
// 前进 3 步记录
router.go(3);
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100);
router.go(100);
router.back
等同于this.$router.go(-1)
,后退到上一个访问的路由。
类似 window.history.back()
router.forward
等同于this.$router.go(1)
,前进到下一个路由。
类似 window.history.forward()
router.resolve
router.resolve
: 用于解析路由的匹配结果。
参数:
-
location:要解析的 URL 地址或路由对象。
-
callback:一个回调函数,用于处理解析结果。
- result 包含解析结果对象
- location:解析后的 URL 地址或路由对象。
- route:与解析结果匹配的路由对象。
- params:解析结果中的动态路由参数。
- query:解析结果中的查询参数。
- fullPath:解析结果的完整路径。
- hash:解析结果的哈希值(如果存在)。
- matched:与解析结果匹配的路由记录数组。
- instances:包含所有匹配路由组件实例的数组。
- result 包含解析结果对象
示例:
// 假设有一个路由配置如下:
// { path: '/user/:id', component: User, props: true }
// 解析 URL 地址为 /user/123 的路由
const resolved = router.resolve({ path: '/user/123' }, (result) => {
console.log(result.route); // 打印匹配的路由对象
console.log(result.params); // 打印动态路由参数 { id: '123' }
console.log(result.query); // 打印查询参数 {}
console.log(result.fullPath); // 打印完整路径 '/user/123'
});
router.currentRoute
router.currentRoute
: 获取当前路由信息
路由重定向
redirect 直接重定向到指定路由
在路由配置中通过redirect
字段直接将一个路由重定向到指定路径
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
path: '/about',
redirect: '/home' // 将/about重定向到/home
}
]
})
redirect 命名路由重定向
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home', // 必须要有name,才能支持 name 重定向
component: Home
},
{
path: '/about',
redirect: { name: 'home' } // 重定向到命名为'home'的路由
}
]
})
redirect 动态重定向
使用函数的方式,可以实现更灵活的重定向配置。该函数会接收当前路由对象作为参数,并返回一个重定向的路径
const router = new VueRouter({
routes: [
{
path: '/users/:id',
component: User,
redirect: to => {
// 当用户访问`/users/:id`时,根据`:id`参数值动态决定重定向到不同的路径。
// 如果`id`为`admin`,则重定向到`/admin`路径,否则重定向到`/users/:id`路径
const { id } = to.params
if (id === 'admin') {
return '/admin'
}
return `/users/${id}`
}
}
]
})
路由传参
params:动态路径,URL路径参数 /user/detail/1
URL路径参数,将参数直接嵌入到URL路径。
参数: object
常用于: 跳转详情页
使用:
1、定义路由规则:
const router = new VueRouter({
routes: [
{
// 带有动态路由参数的路由规则
// 路由匹配:可以匹配任意非斜杠字符
// 写法:使用冒号(:)标记参数,参数名将作为一个占位符来接收实际的值
path: '/user/detail/:id', // 参数名为 id
// path: '/user/detail/:id(\\d+)", // 正则匹配 id 必须是数字
// path: '/user/detail/:id/:other", // 根据实际需求定义多个动态路由参数
component: User,
}
]
})
/user/detail/:id
表示定义一个路径片段(dynamic segments)。当访问/user/detail/1
时,路由会匹配到该规则,并将实际的参数值传递给User
组件
2、路由跳转:
this.$router.push('/user/detail/1')
注意:如果传入的是对象,path 优先级高于 params ,所以params 会被忽略
this.$router.push({ path: '/user/detail/1' })
this.$router.push({ path: '/user/detail', params:{ id: 1 } }) // 无效路由跳转
// 可以将path改成name
this.$router.push({
name:'User',
params:{ id: 1 }
})
3、访问 params
参数:
// 路由匹配时,这些路径参数会被提取,并可以通过`$route.params`对象进行访问
// id 为路由规则定义的参数名
this.$route.params.id;
query:查询参数 /user/detail?id=1
查询参数,将参数作为URL的查询字符串(query string)的一部分进行传递的方式
参数: object
常用于: 存放需要与后端交互的参数
使用:
1、路由跳转:
this.$router.push({ path: '/user/detail', query: { id: 1 }})
2、访问 query
参数:
this.$route.query.id;
hash:/user/detail#step=1
hash 值
url上显示形式:
/user/detail#step=1
/user/detail?id=1#step=1
/user/detail?id=1#step=1&other=xxx
参数: string
常用于: 存放网页需要处理参数
使用:
1、路由跳转:
this.$router.push({ path: '/user/detail', hash: "#step=1" })
this.$router.push({ path: '/user/detail', query: {}, hash: "#step=1&other=xxx" })
this.$router.push({ path: '/user/detail', hash: "#step=1&other=xxx" })
2、访问 hash
参数:
this.$route.hash; // "#step=1&other=xxx"
meta:路由配置中的属性
路由配置中通过自定义的属性来传递数据。
使用:
1、定义路由规则:
const router = new VueRouter({
routes: [
{
path: '/user/detail',
component: User,
meta: { id: 1 }, // 自定义属性
}
]
})
2、访问 meta
属性:
this.$route.meta.id
params
、query
两者区别
query
相当于get
请求,页面跳转的时候,可以在地址栏看到请求参数;params
相当于post
请求,参数不会再地址栏中显示params
是路由的一部分,必须要在路由后面添加参数名;query
是拼接在url
后面的参数,没有也没关系params
一旦设置在路由,params
就是路由的一部分,如果这个路由有params
传参,但是在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容
动态添加路由 V2.2.0+
先明确不是动态路径,而是动态添加路由。
通过动态添加路由 router.addRoutes(routes)
方法 来实现根据特定条件或动态数据生成路由的功能。
思路:
- 首先创建了一个初始的Vue Router实例,并定义了一些静态的路由规则
- 将获取到的动态路由,通过
router.addRoutes(routes)
方法来动态添加路由。routes
参数是一个包含新路由配置对象的数组。
动态路由数据:
- 根据后台返回的数据生成路由
- 根据用户权限动态展示的路由
const router = new VueRouter({
routes: [
// 初始的静态路由配置
{
path: '/',
component: Home,
},
{
path: '/about',
component: About,
}
]
})
// 动态添加路由
const trendRoutes = [
{
path: '/products',
component: Products,
},
{
path: '/contact',
component: Contact,
}
]
router.addRoutes(trendRoutes)
路由嵌套(嵌套路由)
在Vue Router中,可以通过配置嵌套路由来实现路由的嵌套结构。嵌套路由可用于在父路由下定义子路由,实现页面的嵌套和组件的层级关系。以下是一个使用嵌套路由的示例:
const router = new VueRouter({
routes: [
{
path: '/dashboard',
component: Dashboard,
children: [
{
// 以 / 开头的嵌套路径会被当作根路径
// 这让你充分的使用嵌套组件而无须设置嵌套的路径
// path: '/dashboard/overview',
// 或者使用如下,不添加/,默认拼接成 /dashboard/overview
path: 'overview',
// 当 /dashboard/overview 匹配成功
// Overview 会被渲染在 Dashboard 的 <router-view> 中
component: Overview
},
{
path: 'settings',
component: Settings
}
]
}
]
})
在上述示例中,Dashboard
是一个父级路由,它定义了两个子路由:Overview
和Settings
。父级路由的路径是/dashboard
,而子路由的路径是相对于父级路由的,分别是/dashboard/overview
和/dashboard/settings
。
在创建嵌套路由时,需要注意以下几点:
- 在父级路由的组件中使用
<router-view>
标签来作为子组件的占位符,用于渲染子路由对应的组件。 - 子路由的
path
配置是相对于父级路由的,可以使用相对路径或绝对路径。 - 子路由配置应该放在父路由的
children
属性中。 - 嵌套路由可以继续嵌套,形成更深层次的路由结构。
在使用嵌套路由时,可以根据实际需求设置不同的层级关系和嵌套结构,从而构建复杂的页面布局和导航逻辑。在父级路由的组件模板中使用<router-view>
标签,将会根据当前路由的路径动态渲染匹配的子路由组件。
路由懒加载(延迟加载或按需加载)
在单页面应用(SPA)中,如果不使用懒加载,那么应用的所有资源包括JavaScript、CSS和HTML都会在首次进入时一次性加载,这会导致首页加载时间过长,影响用户体验。
为了解决首屏加载这个问题,Vue Router提供了懒加载的功能。
component: () => import(/* webpackChunkName: 'about' */ './views/About.vue')
作用: 只有当用户访问到(需要)某个路由时,相关的组件才会被加载,而不是一开始就加载所有的路由组件。
优点:
- 提高首屏加载速度
- 减少初始加载时的资源体积(组件、图片等各种资源)
- 减少初始加载时的网络请求次数
- 减少内存占用,提高应用的整体性能
- 优化用户体验:懒加载可以让用户在不牺牲太多性能的情况下,快速看到首页的内容,而在用户进一步探索应用时,其他路由的组件才会被加载。
使用: 路由配置文件
const router = new VueRouter({
routes: [
{
path: '/about',
// 使用动态导入延迟加载组件
component: () => import(/* webpackChunkName: 'about' */ './views/About.vue')
},
// 其他路由规则...
]
})
import()
函数动态导入语法: 是实现 组件异步加载/延迟加载 关键语法,代替直接引入组件。当用户导航到某个路由时(路由被访问时),对应的组件才会被异步加载并渲染。
webpackChunkName
: 结合Webpack的代码分割功能,定义 import()
的 webpackChunkName
将模块分割成不同的代码块。可以将每个路由对应的组件打包成一个单独的文件,只有在该路由被访问时才会加载对应的文件。
注意:
- 懒加载只适用于异步加载的路由组件。对于常规(同步)加载的组件,不需要使用懒加载机制。
- 对于小型应用或页面数量较少的应用,懒加载可能带来的性能优势可能不太明显
- 如果所有的路由组件 webpackChunkName 一样,则定义异步加载组件的优势没有体现出来
路由的404页面
通配符路由/捕获所有路由
在路由配置中定义一个通配符路由,用于匹配所有未被定义的路由路径。将该通配符路由配置映射到 404的页面组件。当用户访问一个不存在的路径时,通配符路由就会被激活并匹配到,然后会渲染NotFound
组件,即404页面
const router = new VueRouter({
routes: [
// 其他路由配置...
{
// 会匹配以 `/user-` 开头的任意路径
path: "/user-*";
},
{
path: '*', // 表示该路由会匹配所有未被定义的路径
component: NotFound, // 显示404页面的组件
}
]
})
注意:
- 使用通配符路由时,请确保路由的顺序是正确的。含有通配符的路由应该放在最后。
- 如果你使用了History 模式,请确保 正确配置你的服务器。
当使用一个通配符时,$route.params
内会自动添加一个名为 pathMatch
参数。它包含了 URL 通过通配符被匹配的部分:
// 给出一个路由 { path: '/user-*' }
this.$router.push("/user-admin");
this.$route.params.pathMatch; // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push("/non-existing");
this.$route.params.pathMatch; // '/non-existing'
导航守卫
在全局路由守卫 beforeEach
中处理路由的404页面。检查要跳转的路由是否存在,如果不存在则跳转到404页面。
router.beforeEach((to, from, next) => {
if (router.hasRoute(to.name)) {
// 路由存在,继续跳转
next()
} else {
// 路由不存在,跳转到404页面
next({ path: '/404' })
}
})
监听路由变化
当使用路由参数时,例如从 /detail/1
导航到 /detail/2
,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
watch
复用组件时,想对路由参数的变化作出响应的话,你可以简单地使用 watch
监听 $route
对象:
浅响应
const User = {
template: '<div>...</div>',
watch: {
$route(to, from) {
// 对路由变化做出响应
// to , from 分别表示从哪跳转到哪,都是一个对象
// to.path ( 表示的是要跳转到的路由的地址 eg: /home );
console.log('当前路由', to, '上一个路由', from)
}
}
}
深响应
const User = {
template: '<div>...</div>',
watch: {
"$route.params.login": {
deep: true, // 深层监听
immediate: true, // 立即执行回调函数
// 数据发生变化时执行回调函数
handler (to, from) { }
}
}
}
监听特定的值
const User = {
template: '<div>...</div>',
watch: {
"$route.params.login": function (to, from) {},
}
}
beforeRouteUpdate
使用 2.2 中引入的 beforeRouteUpdate
导航守卫:
const User = {
template: '...',
beforeRouteUpdate(to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
路由模式
Vue2 | Vue3 |
---|---|
history | createWebHistory |
hash | createWebHashHistory |
abstact | createMemoryHistory |
hash
hash 是 URL 中 hash(#)及后面的那部分,例如http://example.com/page#section1
。
常用作锚点在页面内进行导航,改变 URL 中的hash部分不会引起页面刷新。
通过监听 hashchange
事件来响应哈希的变化。改变URL的方式只要这几种:
- 通过浏览器前进后退改变URL
- 通过 a 标签改变URL
- 通过 window.location 改变URL
history
history 提供了 pushState()
、replaceState()
两个方法,这两个方法改变URL 的 path 部分,不会引起页面刷新
通过监听 popstate
事件来响应历史记录的变化
- 通过浏览器前进后退改变URL时,会触发
popstate
事件 - 通过
pushState()
、replaceState()
、a 标签来改变URL时,不会触发popstate
事件- 可以拦截
pushState()
、replaceState()
的调用和 a 标签的点击事件来检测 URL 变化
- 可以拦截
- 通过js调用 history 的 back、go、forward 方法可触发该事件
hash 和 history 的区别
哈希(Hash)和历史记录(History)是Web开发中常用的两种管理页面状态和导航的方式,它们有一些明显的区别:
表现不同:
-
原理不同:
- hash 通过监听
hashchange
事件来响应哈希的变化 - history 通过监听
popstate
事件来响应历史记录的变化
- hash 通过监听
-
url不同: history 没有符号标识,看上去更加优雅、简洁
-
服务端: hash 不会触发服务端的请求;History 会触发服务端请求
-
部署: history部署的时候需要特殊配置,web服务器需要做回退处理,否则会出现刷新页面 404 的问题
兼容性: 由于 history 是 H5 新特性,兼容 IE >= 10 以上浏览器;hash能兼容ie8
使用: 在Vue中使用上是一样的
Nginx 配置 history 模式
try_files
解读:
$uri
:尝试找文件$uri/
:尝试找地址/admin/index.html
:前面两种方式都找不到,回退到 主页 index.html