1. Installation
1.1. Add dependency
npm install vue-router
1.2. Introduced in the project
Take the latest vue-cli3 architecture as an example, add it to main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
More generally, there is generally a dedicated routing js file, such as router.js
Only router.js is introduced in main.js. And add the above quoted part in router.js. In the future, the relevant routing configuration is configured in router.js.
The directory organization of each js file mentioned above is as follows:
src
------ main.js
------ router
------------ router.js
1.3. Examples
First paste some examples of actual combat to understand intuitive usage
main.js
import 'babel-polyfill'
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
import router from './router/router'
import store from './vuex/store'
import api from './api/api'
import Vant from 'vant'
import 'vant/lib/index.css'
import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll)
Vue.use(Vuex)
Vue.use(Vant)
Vue.prototype.$api = api
new Vue({
router, // 通过 router 选项,提供了一种机制将 “路由” 从根组件注入到每一个子组件中,子组件能通过 this.$router 访问
store, // 通过 store 选项,提供了一种机制将 “状态” 从根组件注入到每一个子组件中,子组件能通过 this.$store 访问
render: h => h(App)
}).$mount('#app')
router.js
import Vue from 'vue'
import Router from 'vue-router'
const home = () => import('@/views/index/index.vue')
const airport = () => import('@/components/airport/airport.vue')
const orderDetail = () => import('@/views/order/order-detail.vue')
Vue.use(Router)
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: home
},
{
path: '/airport',
name: 'airport',
component: airport
},
{
path: '/orderDetail/:orderNo',
name: 'orderDetail',
component: orderDetail
}
]
})
2. Usage
2.1. The first demo
- HTML
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
- JS
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定义路由
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
routes // (缩写) 相当于 routes: routes
})
// 4. 创建和挂载根实例。
// 通过 router 配置参数注入路由从而让整个应用都有路由功能
const app = new Vue({
router // (缩写) 相当于 router: router
}).$mount('#app')
By injecting the router, we can
this.$router
access the router within any component , orthis.$route
access the current route:
// Home.vue
export default {
computed: {
username () {
return this.$route.params.username
}
},
methods: {
goBack () {
window.history.length > 1
? this.$router.go(-1)
: this.$router.push('/')
}
}
}
2.2. Dynamic route matching
That is, the matching when the request url contains dynamic parameters, similar to this form: /user/:id , similar to @pathVariable in springMVC
Here is a basic chestnut to understand the usage:
- Request path: /user/:id
- Application scenario: For example, users with different IDs can be mapped to the User component
- Then in the User component, you can get the id attribute in the params parameter object on the dynamic url through this.$route.params.id
You can set multiple "path parameters" in a route, and the corresponding values will all be set to the $route.params
middle. E.g:
mode | Match path | $route.params |
---|---|---|
/user/:username | /user/evan | { username: 'evan' } |
/user/:username/post/:post_id | /user/evan/post/123 | { username: 'evan', post_id: '123' } |
In
$route.params
addition, the$route
object also provides other useful information, for example,$route.query
(if there are query parameters in the URL),$route.hash
and so on.
2.3. Nested routing
For example , there is usually a top rendering exit <router-view /> in App.vue
<template>
<div id="app" class="app">
<router-view />
</div>
</template>
When the access / user / 1 format treat User outlet assembly to render the topmost <router-view /> in
At the same time, the User component contains nested rendering exits <router-view />
For example, User
add a <router-view /> to the template of the component :
const User = {
template: `
<div class="user">
<h2>User {
{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
To render components in nested exits, you need VueRouter
to use children
configuration in the parameters :
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
children
Configuration is routes
an array of routing configuration like configuration!
At this point, based on the above configuration, when you visit /user/foo
, User
the exit will not render anything, because there is no matching sub-route. If you want to render something, you can provide an empty sub-route:
const router = new VueRouter({
routes: [
{
path: '/user/:id', component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 <router-view> 中
{ path: '', component: UserHome },
// ...其他子路由
]
}
]
})
2.4. Programmatic navigation
2.4.1. router.push(location, onComplete?, onAbort?)
Declarative | Programmatic |
---|---|
<router-link :to="..."> |
router.push(...) |
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
Note: If provided path
, it params
will be ignored!
Because the path option represents the complete URL, and params is part of the URL, there will be ambiguity at the same time!
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
2.4.2. router.replace(location, onComplete?, onAbort?)
It is router.push
very similar, the only difference is that it does not add a new record to history, but is the same as its method name—replace the current history record.
Declarative | Programmatic |
---|---|
<router-link :to="..." replace> |
router.replace(...) |
2.4.3. router.go(n)
The parameter of this method is an integer, which means how many steps forward or backward in the history record, similar window.history.go(n)
.
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
2.5. Naming Routes
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user', // 给路由起个名字而已
component: User
}
]
})
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
or
router.push({ name: 'user', params: { userId: 123 }})
You can call it!
2.6. Redirect
When the user visits /a
, the URL will be replaced with /b
, and then the matching route will be /b
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
}}
]
})
2.7. Aliases
/a
The alias of is /b
, which means that when the user visits /b
, the URL will remain as /b
, but the route matching will be /a
, just like the user visits /a
.
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
2.8. Routing component parameter transfer
As the name implies, during the routing process, the routing parameters are converted into component attributes, and the parameters are passed in the way of passing values between components!
why do this?
Using
$route
it in a component makes it highly coupled with its corresponding route, so that the component can only be used on certain URLs, limiting its flexibility.
2.8.1. Usage comparison
And $route
coupling
const User = {
template: '<div>User {
{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
By props
decoupling
const User = {
props: ['id'],
template: '<div>User {
{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true }
]
})
Boolean mode
If it props
is set true
, it route.params
will be set as a component property.
Object mode
If it props
is an object, it will be set as a component property as it is. props
Useful when it is static.
const router = new VueRouter({
routes: [
{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
]
})
Function mode
You can create a function to return props
. This way you can convert parameters to another type, combine static values with route-based values, and so on.
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
]
})
The URL /search?q=vue
will {query: 'vue'}
be passed to the SearchUser
component as an attribute .