作者:Matt Maribojoc翻译:疯狂的技术宅
能够构建出色的单页应用程序(SPA)是 Vue.js 最具有吸引力的功能之一。
SPA 非常好,因为它们不需要在每次更改路由时都去加载页面。这就意味着一旦加载了全部内容,就可以真正快速地对视图进行切换,并提供出色的用户体验。
如果你想要基于 Vue 去构建 SPA,则需要 Vue 路由。
在本教程中,我将介绍设置 Vue Router 的基础知识,并研究一些更高级的技术,例如:
- 动态路由匹配
- 导航挂钩(Navigation Hook)
Vue 路由是什么?
Vue 路由有助于在浏览器的 URL 或历史记录与 Vue 组件之间建立链接,从而允许某些路径渲染与之关联的任何一个视图。
VueCore 小组成员 Eduardo San Martin Morote 在他的 VueConf Toronto演讲中,对 Vue 路由背后的设计思想做了大量的分享。
Morote 讨论了在灵活的路由(开发人员有更多的自主权,但是需要编写更多的代码)与死板的路由(开发人员拥有的自主权较少,但是路由涵盖了更多的应用场景)之间进行权衡时,其背后的决策过程。
基于配置的 Vue 路由旨在为开发人员提供用于常见应用场景的工具,并灵活应对独特的问题。
在继续介绍一些更高级的 Vue 路由之前,先了解一下基础知识。
Vue 路由的快速设置
首先是快速创建一个 Vue Router 的简单例子。
虽然你可以用 vue-cli 轻松添加 Vue 路由,但是我认为你应该知道该怎样自己进行操作。这样才能够真正了解Vue 路由的每个细节。
首先用 npm install vue-router
把 Vue Router 添加到我们的项目中。然后通过 src/main.js
文件将其包含在 Vue 实例中。
import Vue from 'vue'
import App from './App.vue'
import router from './router'// loads from src/router/index.js
new Vue({
router,
render: h => h(App),
}).$mount('#app')
完成所有设置后,开始创建路由。
在 src 内,创建一个 src/router
文件夹,其中的 index.js
文件包含以下内容。
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Profile from '../views/Profile.vue'
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: Home
},
{
path: '/profile',
name: 'profile',
component: Profile
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
这个代码段用了两个路由组件匹配来初始化 Vue Router。我不会在这里介绍 Home 和 Profile 组件的详细信息,你只需要假设它们分别输出 “home” 和 “profile” 就行了。
显示路由视图
前面已经设置了 Vue 路由,但是还没有查看效果的方式。
这时就需要 <router-view>
元素发挥作用了。从本质上讲,router-view 元素为 Vue Router 提供了一个位置,用来渲染当前 URL 被解析后对应的组件。
对于这个例子,我们将其放在 App.vue
根组件中。再添加一些链接,以便可以在两个路由之间切换。 Vue Router 使用称为 <router-link>
的特殊链接元素,这些元素的 to
属性能够映射到组件。
<template>
<div id="app">
<router-link to='/'>Home</router-link>
<router-link to='/profile'>Profile</router-link>
<router-view />
</div>
</template>
运行我们的应用时,应该能够看到 home 组件渲染。如果单击路由链接元素,那么内容将会被更改,同时 URL 也会更改!
下面深入了解 Vue Router 的更多细节。
以编程方式更改路由
在前面的示例中,我们使用 <router-link>
在不同的路线之间导航。从本质上讲,这些等效于 Vue Router 的<a>
标签(实际上,它们可以编译为 <a>
标签)。
但是另一种更改路由的方法是用 router.push
方法以编程方式进行导航。与使用 <router-link>
类似,router.push
接受通过使用其路径或名称的字符串或对象映射到一个路由。
this.$router.push({ path: '/profile' })
// OR
this.$router.push({ name: 'profile' })
使用此方法传递 URL 参数或查询也很容易。只需要添加一个 params
或 query
参数即可。
this.$router.push({
path: '/profile',
params: { username: 'helloworld' },
query: { source: 'tutorial' }
})
历史记录模式和哈希模式之间的区别
Vue 路由的 URL 有两种模式:历史记录和哈希模式。
-
哈希模式(默认)——使用 URL 哈希来模拟 URL,例如
mypage.com/#profile
-
历史记录——看起来像一个典型的 URL,并使用
history.pushState
来避免页面被重新加载;例如mypage.com/profile
我们的路由用了历史记录模式,因为我个人喜欢标准 URL 外观。
处理动态路由
你可以把 URL 模式与组件进行匹配,而不必对每个可能的路径进行硬编码。这对于配置文章页面、个人资料页面和其他可以动态创建或删除的内容非常有用。
用冒号 :
在 Vue 路由中定义动态路径。例如,如果我们要动态匹配文章页面,则路由应如下所示。
{
path: '/post/:postID',
name: 'post',
component: ArticlePage
}
这个路由会把所有遵循 /post/:postID
模式的 URL 导航到相同的 ArticlePage.vue 组件。
如果想要在组件内部获取 postID,有两种方法可以实现。
- 我们的 postID 可以通过
$route.params
对象在 ArticlePage 中访问 - 我们可以把文章 ID 作为 prop 传递给你的组件。
我推荐使用第二种方法,因为它可以使你构建更多的不依赖于特定 URL 格式的可重用组件。
只需在路线中添加 props:true
即可。添加该属性后,我们的动态路由应如下所示。
{
path: '/post/:postID',
props: true,
name: 'post',
component: ArticlePage
}
在组件中,必须确保在声明 prop 时要与在路由中声明的名称相同。
<template>
<div>
{{ postID }}
</div>
</template>
<script>
export default {
props: {
postID: String
}
}
</script>
在更完整的项目中,我们通常会采用路由传递的 prop 值,并通过 API 调用来加载相应的内容。但是一旦可以访问组件内部的 prop 时,就可以使用它进行任何操作。
导航守护简介
导航守护是 Vue Router 中更高级的内容之一。它们是路由过程中的 Hook,可让你重定向、取消或修改导航。
导航守护有三种类型:
- 全局守护
- 特定路由的守护
- 在组件中的守护
此外,守护可以接受三个参数:
-
to
:我们要到达的那个路由 -
from
:要离开的路由 -
next
:用于解决 Hook 的函数;根据传递给下一个方法的参数,我们的路由将处理不同的导航 -
next(false)
:中止导航,不离开 from 路由-
next('/ home')
:把我们的导航重定向到指定的路由
-
-
next()
:如果没有参数,则会简单地将其移至下一个 Hook;确认导航没有剩余的Hook
1. 全局守护
全局守护的措施主要有两种:router.beforeEach()
与 router.afterEach()
分别在导航解析之前和之后运行。
让我们来看一个例子。在此方法中,首先检查用户是否有权访问某个页面,如果没有访问权,将会阻止路由解析。请注意,每次 Hook 运行时仅调用一次。
router.beforeEach( (to, next, from) => {
if (to.path === '/profile') {
if (!hasAccess(to.path)) { // just some arbitrary conditional
next(false) // deny access to this page
} else {
next() // keep moving on to next hook
}
} else {
next() // keep moving on to next hook
}
})
2. 特定于路由的守护
当我们在 Vue Router 中声明路由时,还可以添加一个 beforeEnter
函数,其功能类似于全局 beforeEach
路由,但是它可以包含特定于路由的逻辑。
{
path: '/post/:postID',
props: true,
name: 'post',
component: ArticlePage,
beforeEnter: (to, from, next) => {
// some logic here
}
}
3.在组件中的守护
更具体地说,我们可以在组件的 options 对象中插入导航守护,总共有三种:
-
beforeRouteEnter (to, from, next)
:在确认此路由之前调用;该组件尚未创建。 -
beforeRouteUpdate (to, from, next)
:在切换路由时调用;但新路由也可以确定此组件。 -
beforeRouteLeave(to, from, next)
:当离开这个组件时被调用
需要注意的是,在确认导航之前和实际创建组件之前,将会调用 beforeRouteEnter
。此时我们还没有访问this
。
为了解决这个问题,beforeRouteEnter
允许我们将回调传给下一个方法,该方法将在组件实际创建后立即执行。
beforeRouteEnter (to, from, next) {
next((vm) => {
// vm = 'this'
console.log(vm)
})
}
总结
希望本文能够帮你你学习一些基本和高级的 Vue 路由技术。
探索一个灵活但易用的路由所涉及的设计思路非常很有趣。在听过 Morote 的演讲之后,我认为后续可能还会有更多的改进!
前端刷题神器
扫码进入前端面试星球?,解锁刷题神器,还可以获取800+道前端面试题和一线常见面试高频考点。
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13个帮你提高开发效率的现代CSS框架
- 快速上手BootstrapVue
- JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切
- WebSocket实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30分钟用Node.js构建一个API服务器
- Javascript的对象拷贝
- 程序员30岁前月薪达不到30K,该何去何从
- 14个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把HTML转成PDF的4个方案及实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。