文章目录
- 一、安装
- 二、基础使用
- 1、简单的示例
- 2、动态路由
- 2.1 定义动态路径参数
- 2.2 获取动态路径的参数
- 2.3 捕获所有路由
- 3、嵌套路由
- 4、编程式的导航
- 4.1 router.push
- 4.2 router.replace
- 4.3 router.go(n)
- 5、命名路由
- 6、重定向
- 三、进阶
- 1、导航守卫
- 1.1 全局前置守卫
- 1.2 全局后置钩子
- 1.3 路由独享的守卫
- 1.4 组件内的守卫
- 完整的导航解析流程
- 2、路由懒加载
一、安装
NPM
注意:vue2中需使用 v.3x 版本
npm install vue-router@3.0.0 --save
vue-router v3.x 文档:文档链接
二、基础使用
1、简单的示例
src/main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'// 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
})// 4. 通过 Vue.use() 明确地安装路由功能
Vue.use(VueRouter);// 5. 创建和挂载根实例。
// 通过 router 配置参数注入路由,让整个应用都有路由功能
new Vue({router,render: h => h(App),
}).$mount('#app')
src/App.vue
<template><div id="app"><p><!-- 使用 router-link 组件来导航. --><!-- 通过传入 `to` 属性指定链接. --><!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --><router-link to="/foo">Foo</router-link><br /><router-link to="/bar">Bar</router-link></p><!-- 路由出口,路由匹配到的组件将渲染在这里 --><router-view></router-view></div>
</template><script>
export default {name: "App",components: {},
};
</script>
2、动态路由
2.1 定义动态路径参数
动态路径参数以冒号开头
const User = {template: '<div>User</div>'
}const router = new VueRouter({routes: [// 动态路径参数 以冒号开头{ path: '/user/:id', component: User }]
})
现在像 /user/123 和 /user/456 都将映射到相同的路由
2.2 获取动态路径的参数
当匹配到一个路由时,参数值会被设置到 this.$route.params
,可以在每个组件内使用
const User = {template: '<div>User {{ $route.params.id }}</div>'
}
可以通过 $route.params
查看所有的参数信息
$route
对象还提供了其它有用的信息
const User = {template: '<div>User {{ $route.params.id }}</div>',created: function () {console.log(this.$route)}
}
当路由是 /user/101 时,$route 示例:
2.3 捕获所有路由
可以使用通配符 (*):
{// 会匹配所有路径path: '*'
}
{// 会匹配以 `/user-` 开头的任意路径path: '/user-*'
}
3、嵌套路由
要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children
配置:
src/main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'import UserView from './components/UserView.vue'
import FooView from './components/FooView.vue'
import BarView from './components/BarView.vue'const routes = [{path: '/user',component: UserView,children: [{// 当 /user/foo 匹配成功,// FooView 会被渲染在 User 的 <router-view> 中path: 'foo',component: FooView},{// 当 /user/bar 匹配成功,// BarView 会被渲染在 User 的 <router-view> 中path: 'bar',component: BarView},]},
]const router = new VueRouter({routes
})Vue.use(VueRouter);new Vue({router,render: h => h(App),
}).$mount('#app')
顶层 <router-view>
出口,App.vue
<template><div id="app"><p><router-link to="/user/foo">Foo</router-link><br /><router-link to="/user/bar">Bar</router-link><br /></p><!-- 这个是顶层的 router-view --><router-view></router-view></div>
</template><script>
export default {name: "App",components: {},
};
</script>
组件同样可以包含自己的嵌套 <router-view>
组件 UserView.vue
<template><div class="user"><h2>User</h2><router-view></router-view></div>
</template>
组件 BarView.vue
<template><div>bar</div>
</template>
组件 FooView.vue
<template><div>foo</div>
</template>
要注意,以 / 开头的嵌套路径会被当作根路径
4、编程式的导航
4.1 router.push
这个方法会向 history 栈添加一个新的记录
代码实现路由跳转:
router.push(location, onComplete?, onAbort?)
声明式 | 编程式 |
---|---|
<router-link :to="..." > | router.push(...) |
该方法的参数可以是一个字符串路径,或者一个描述地址的对象,示例:
<template><div id="app"><div><button @click="routeUser">字符串跳转user</button><button @click="routeFoo">对象跳转foo</button><button @click="routeBarParams">对象跳转带参数Params</button><button @click="routeBarQuery">对象跳转带参数Query</button></div><!-- 这个是顶层的 router-view --><router-view></router-view></div>
</template><script>
export default {name: "App",components: {},methods: {routeUser() {// 字符串this.$router.push("/user");},routeFoo() {// 对象this.$router.push({path: "/foo"});},routeBarParams() {// 命名的路由(带name属性)this.$router.push({ name: 'bar', params: { id: '123' }})},routeBarQuery() {// 带查询参数,变成 /bar?id=456this.$router.push({ path: '/bar', query: { id: '456' }})// 注意:如果提供了 path,params 会被忽略// 下面的 params 不生效// this.$router.push({ path: '/bar', params: { id }}) // -> /user},},
};
</script>
4.2 router.replace
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录
router.replace(location, onComplete?, onAbort?)
声明式 | 编程式 |
---|---|
<router-link :to="..." replace> | router.replace(...) |
4.3 router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。
示例:
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)// 后退一步记录,等同于 history.back()
router.go(-1)// 前进 3 步记录
router.go(3)
5、命名路由
可以在创建 Router 实例的时候,在 routes 配置中使用 name
给某个路由设置名称:
const router = new VueRouter({routes: [{path: '/user/:userId',name: 'user',component: User}]
})
6、重定向
重定向也是通过 routes 配置来完成,使用 redirect
下面例子是从 /a 重定向到 /b:
const router = new VueRouter({routes: [{ path: '/a', redirect: '/b' }]
})
三、进阶
1、导航守卫
1.1 全局前置守卫
使用 router.beforeEach
注册一个全局前置守卫:
const router = new VueRouter({ ... })router.beforeEach((to, from, next) => {// ...
})
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
- next(): 进行管道中的下一个钩子
- next(false): 中断当前的导航
- next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址
确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错
身份时重定向到 /login 的示例:
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) {next({ name: 'Login' })} else {next()}
})
1.2 全局后置钩子
也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {// ...
})
1.3 路由独享的守卫
可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({routes: [{path: '/foo',component: Foo,beforeEnter: (to, from, next) => {// ...}}]
})
1.4 组件内的守卫
可以在路由组件内直接定义以下路由导航守卫:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const Foo = {template: `...`,beforeRouteEnter(to, from, next) {// 在渲染该组件的对应路由被 confirm 前调用// 不!能!获取组件实例 `this`// 因为当守卫执行前,组件实例还没被创建},beforeRouteUpdate(to, from, next) {// 在当前路由改变,但是该组件被复用时调用// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。// 可以访问组件实例 `this`},beforeRouteLeave(to, from, next) {// 导航离开该组件的对应路由时调用// 可以访问组件实例 `this`}
}
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 10.调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入
2、路由懒加载
就是当路由被访问的时候才加载对应的组件
示例:
const Foo = () => import('./Foo.vue')const router = new VueRouter({routes: [{ path: '/foo', component: Foo }]
})