vue-router
本文是基于官网学习, 官网具体学习目录: vue-router https://router.vuejs.org/zh-cn/
一, 安装
基于 vue-cli 脚手架安装还是蛮简单的: 在文件当前目录下运行:
npm install vue-router
如果在一个模块化工程中使用它, 必须要通过 Vue.use() 明确地安装路由功能:
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- Vue.use(VueRouter)
脚手架安装教程: 脚手架安装教程 https://segmentfault.com/a/1190000008049815
其他类型安装详见官网: 安装 https://router.vuejs.org/zh-cn/installation.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` 属性指定链接. -->
- <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
- <router-link to="/foo">Go to Foo</router-link>
- <router-link to="/bar">Go to Bar</router-link>
- </p>
- <!-- 路由出口 -->
- <!-- 路由匹配到的组件将渲染在这里 -->
- <router-view></router-view>
- </div>
- <script>
- // 0. 如果使用模块化机制编程, 导入 Vue 和 VueRouter, 要调用 Vue.use(VueRouter)
- // 1. 定义 (路由) 组件.
- // 可以从其他文件 import 进来
- const Foo = {
- template: '<div>foo</div>'
- }
- const Bar = {
- template: '<div>bar</div>'
- }
- // 2. 定义路由
- // 每个路由应该映射一个组件. 其中 "component" 可以是
- // 通过 Vue.extend() 创建的组件构造器,
- // 或者, 只是一个组件配置对象.
- // 我们晚点再讨论嵌套路由.
- 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
- }).$mount('#app')
- // 现在, 应用已经启动了!
- </script>
- <!-- 要注意, 当 <router-link> 对应的路由匹配成功, 将自动设置 class 属性值 .router-link-active -->
- <style>
- .router-link-active {
- color: red;
- }
- </style>
效果:
这个案例, 就是不同路径显示不同组件.
三, 动态路由匹配
我们经常需要把某种模式匹配到的所有路由, 全都映射到同个组件. 比如 / user/name,/user/age,/user/haha 都要映射到 user 组件, 怎么做呢?
- <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">
- <p>
- <router-link to="/user/foo">/user/foo</router-link>
- <router-link to="/user/bar">/user/bar</router-link>
- </p>
- <router-view></router-view>
- </div>
- <script>
- // 一个路径参数使用冒号 : 标记. 当匹配到一个路由时,
- // 参数值会被设置到 this.$route.params, 可以在每个组件内使用. 于是, 我们可以更新 User 的模板
- // 输出当前用户的 ID
- const User = {
- template: `<div>User {{ $route.params.id }}</div>`
- }
- // 动态路径参数 以冒号开头
- // 现在呢, 像 /user/foo 和 /user/bar 都将映射到相同的路由.
- const router = new VueRouter({
- routes: [{
- path: '/user/:id',
- component: User
- }]
- })
- const app = new Vue({
- router
- }).$mount('#app')
- </script>
- <style>
- .router-link-active {
- color: red;
- }
- </style>
效果:
你可以在一个路由中设置多段路径参数, 对应的值都会设置到 $route.params 中. 例如:
模式 | 匹配路径 | $route.params | |
---|---|---|---|
/user/:username | /user/evan | { username: 'evan' } | |
/user/:username/post/:post_id | /user/evan/post/123 | { username: 'evan', post_id: 123 } |
四, 嵌套路由
嵌套路由是个常见的需求, 假设用户能够通过路径 / home/news 和 / home/message 访问一些内容, 一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
实现嵌套路由有两个要点:
在组件内部使用 < router-view > 标签
VueRouter 的参数中使用 children 配置
<div id="app">
<router-view></router-view>
</div>
这里的 <router-view> 是最顶层的出口, 渲染最高级路由匹配到的组件. 同样地, 一个被渲染组件同样可以包含自己的嵌套 <router-view>. 例如, 在 User 组件的模板添加一个 <router-view>
- const User = {
- template: `
- <div class="user">
- <h2>User {{ $route.params.id }}</h2>
- <router-view></router-view>
- </div>
- `
- }
要在嵌套的出口中渲染组件, 需要在 VueRouter 的参数中使用 children 配置
- 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
- }
- ]
- }
- ]
- })
要注意, 以 / 开头的嵌套路径会被当作根路径. 这让你充分的使用嵌套组件而无须设置嵌套的路径.
此时, 基于上面的配置, 当你访问 /user/foo 时, User 的出口是不会渲染任何东西, 这是因为没有匹配到合适的子路由. 如果你想要渲染点什么, 可以提供一个 空的 子路由:
- const router = new VueRouter({
- routes: [
- {
- path: '/user/:id', component: User,
- children: [
- // 当 /user/:id 匹配成功,
- // UserHome 会被渲染在 User 的 <router-view> 中
- { path: '', component: UserHome },
- // ... 其他子路由
- ]
- }
- ]
- })
综合小案例:
- <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">
- <p>
- <router-link to="/user/foo">/user/foo</router-link>
- <router-link to="/user/foo/profile">/user/foo/profile</router-link>
- <router-link to="/user/foo/posts">/user/foo/posts</router-link>
- </p>
- <router-view></router-view>
- </div>
- <script>
- const User = {
- template: `
- <div class="user">
- <h2>User {{ $route.params.id }}</h2>
- <router-view></router-view>
- </div> `
- }
- const UserHome = { template: '<div>Home</div>' }
- const UserProfile = { template: '<div>Profile</div>' }
- const UserPosts = { template: '<div>Posts</div>' }
- const router = new VueRouter({
- routes: [{
- path: '/user/:id',
- component: User,
- children: [{
- ///user/:id / 匹配到 UserHome 组件, 如果你是 / user/:id/home 是匹配不到任何组件的, 因为 children 里没有 home 路径
- path: '',
- component: UserHome
- },
- { ///user/:id/profile 匹配到 UserProfile 组件
- path: 'profile',
- component: UserProfile
- },
- { ///user/:id/posts 匹配到 UserPosts 组件
- path: 'posts',
- component: UserPosts
- }
- ]
- }]
- })
- const app = new Vue({
- router
- }).$mount('#app')
- </Script>
效果:
五, 编程式路由
1,router.push
上面几种路由都是直接在页面点击进行跳转, 但在我们实际开发过程中, 有很多按钮在执行跳转之前, 还会执行一系列方法, 这时可以使用 this.$router.push(location) 来修改 url, 完成跳转
想要导航到不同的 URL, 则使用 router.push 方法. 这个方法会向 history 栈添加一个新的记录, 所以, 当用户点击浏览器后退按钮时, 则回到之前的 URL.
当你点击 <router-link> 时, 这个方法会在内部调用, 所以说, 点击
<router-link :to="...">
等同于调用 router.push(...).
声明式 | 编程式 |
---|---|
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' }})
注意: 如果提供了 path,params 会被忽略, 上述例子中的 query 并不属于这种情况. 取而代之的是下面例子的做法, 你需要提供路由的 name 或手写完整的带有参数的 path
- 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
同样的规则也适用于 router-link 组件的 to 属性.
2.router.replace
跟 router.push 很像, 唯一的不同就是, 它不会向 history 添加新记录, 而是跟它的方法名一样 -- 替换掉当前的 history 记录.(下面会具体说明)
声明式 | 编程式 |
---|---|
router.replace(...) |
3,router.go(n)
这个方法的参数是一个整数, 意思是在 history 记录中向前或者后退多少步, 类似
- 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)
4, 三个比较说明:
1.this.$router.push():
跳转到不同的 url, 但这个方法回向 history 栈添加一个记录, 点击后退会返回到上一个页面.
2.this.$router.replace()
同样是跳转到指定的 url, 但是这个方法不会向 history 里面添加新的记录, 点击返回, 会跳转到上上一个页面. 上一个记录是不存在的.
3.this.$router.go(n)
相对于当前页面向前或向后跳转多少个页面, 类似
window.history.go(n)
.n 可为正数可为负数. 正数返回上一个页面
4, 在什么情况用 push, 或者在上面情况用 replace, 个人理解:
一般情况下, 要做前进后退的浏览记录管理的, 基本上都是用 router.push(), 但是也是有一些特殊情况需要用到 router.replace(). 比如, 有一个授权页, 用户在按流程操作时, 某一步需要授权, 是直接跳到授权页, 授权页提交授权请求, 直到成功授权后, 跳到流程中的下一步操作的地址. 此处, 授权请求的那页面应该用 replace 去替换掉自身的访问记录, 防止用户跳到下一步流程后按后退键回退到授权页, 而导致重复授权, 简单来讲就是你跳过来了, 就不让你后退又到上一个页面.
举例:
- <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">
- <button type="button" @click="fooClick">/user/foo</button>
- <button type="button" @click="profileClick">/user/foo/profile</button>
- <button type="button" @click="postsClick">/user/foo/posts</button>
- <router-view></router-view>
- </div>
- <script>
- // 定义了三个组件
- const UserHome = { template: '<div>Home</div>' }
- const UserProfile = { template: '<div>Profile</div>'}
- const UserPosts = { template: '<div>Posts</div>' }
- // 匹配了三个路由
- const router = new VueRouter({
- routes: [{
- path: '/user/foo',
- component: UserHome,
- }, {
- path: '/user/foo/profile',
- component: UserProfile,
- }, {
- path: '/user/foo/posts',
- component: UserPosts,
- }]
- })
- const app = new Vue({
- el: '#app',
- router,
- data: {
- foo: '/user/foo',
- profile: '/user/foo/profile',
- posts: '/user/foo/posts'
- },
- methods: {
- fooClick: function(event) {
- this.$router.push({
- path: this.foo
- });
- },
- profileClick: function(event) {
- this.$router.push({
- path: this.profile
- });
- },
- postsClick: function(event) {
- this.$router.push({
- path: this.posts
- });
- }
- }
- })
- </Script>
页面:
测试结果: 当使用 this.$router.push, 时, 前进一步后退一步都会退到上一次进入的页面, 而使用 this.$router.replace 并不不会调到上一个页面.
想太多, 做太少, 中间的落差就是烦恼. 想没有烦恼, 要么别想, 要么多做. 中尉[19]
来源: https://www.cnblogs.com/qdhxhz/p/9005836.html