[TOC]
## 前言
设置vue的router是必备的知识点,通过本篇你将得到官网基本的知识点解析以及相关的理解。部分知识点还会有案例提供。
## 官网文档
* [官方vue-router2.0的中文文档](https://router.vuejs.org/zh-cn/)
## 基础
### 页面使用
~~~
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. 默认会被渲染成一个 `<a>` 标签 -->
    <!-- 通过传入 `to` 属性指定链接.  如果你想在新页面打开,那么设置target="_blank"即可-->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>
~~~
### 动态路由
* 访问路径中带查询参数的,影响路由定义
  ~~~
  const router = new VueRouter({
    routes: [
      // 动态路径参数 以冒号开头
      { path: '/bookDetail/:id', component: bookDetail }
    ]
  })
  //页面中定义
    <router-link :to="'/bookDetail/' +book.id" > {{book.id}}</router-link>
   //编程式导航
   router.push({ name: 'bookDetail', params: { id: 123 }})
  ~~~
  |  模式  | 匹配路径   | $route.params   |
  | --- | --- | --- |
  |   /user/:username | user/evan   |  { username: 'evan' }  |
  |   /user/:username/post/:post_id |   /user/evan/post/123 |{ username: 'evan', post_id: 123 }    |
* 除了 $route.params 外,$route 对象还提供了其它有用的信息,例如,$route.query(如果 URL 中有查询参数)、$route.hash 等等。
详细参考地址:[route-object](https://router.vuejs.org/zh-cn/api/route-object.html)。
对于$route.query的使用:url中直接拼接就可以,不影响路由定义
~~~
//页面中
<router-link :to="'infoplan?id='+scope.row.id">
//脚本导航,带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }}
//使用
this.$route.query.id
//路由定义
path:'infoplan'
~~~
### 路由参数变化时,组件不会渲染
解决方案:因为vue默认是同一路由时不会重复渲染,所以需要做监听,当参数变化时,重新获取数据。写法如下:
~~~
 watch: {
    '$route' (to, from) {
      // 对路由变化作出响应...
    }
  }
~~~
###  定义路由
指定的参数有path,name,component,其中path为#/之后的路径,name为路由别称,component为路由指向的组件。针对任何不在路由设定之内的可以使用path:'*' 来匹配,针对需要拦截的情况使用钩子函数。
~~~
// 每个路由应该映射一个组件。 其中"component" 可以是
//通过 Vue.extend() 创建的组件构造器, 或者,只是一个组件配置对象。
//定义工具函数 方法引入需要的组件(推荐使用),这个是路由的懒加载的写法。
const compLoad = (name) => (resolve) => require([`@/components/${name}`], resolve)
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]
~~~
### 嵌套路由
实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,最常见的后台系统以及多层递进的窗口都可能是多层路由的。在直接的父路由的情况下,可能没有对应的组件渲染,这时候需要提供一个默认的路由组件。
要在嵌套的出口中渲染组件,需要在 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
        }
      ]
    }
  ]
})
~~~
* **要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径**。
* 
###  router 实例,配置使用
~~~
//  router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写)相当于 routes: routes
})
//配置使用router
var app=new Vue({
router
}).$mount('#app')
~~~
### 声明式导航(to绑定链接地址)
`<router-link :to="...">`
### 编程式导航
除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
~~~
//基本格式
router.push(location)
// 字符串,不带任何参数的
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由,带简单的参数列表的,会用多个斜杠分开
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
~~~
### 获取url参数
* 如果你想获取url上的参数,需要保证传入时按照规定的格式,那么你规定路由时以及使用参数参考下面的。多参的时候加&连接就可以了。下面规定的是不带参数名称的形式。
  ~~~
  //页面书写
  <router-link :to="'/bookDetail/' +book.id+'&'+book.type" > {{book.id}}{{book.pubdate}}</router-link>
  //也可以通过脚本push跳转,也称为编程式导航
  this.$router.push({name:'infoplan',params:{id:id}})
  //规定路由参数
  {
        path: '/bookDetail/:id&:type',
        name: 'bookDetail',
        component: vueLoad('bookDetail')
      }
   //使用路由参数,写在created函数中生效,这里是route不是router,切记
   created(){
    this.id=this.$route.params.id;
   this.type=this.$route.params.type;
   }
  
  ~~~
  
  
### 特殊路由 404
因为其他错误页面配置与正常页面没有什么差别,只有404页面是特殊的,404页面针对的是当前地址匹配不到任何路由地址,所以其地址匹配是正则形式的,除了这点还要注意404的路由必须写在所有路由最后的位置,否则会覆盖其他路由不能生效。
~~~
{
      path: '/*',
      name: '404',
      component: _import('notFound')
    }
~~~
  
## 进阶
### 路由懒加载
也就是进入页面时才加载对应的路由资源,更加方便,打包时也打包出更多的文件。可以采用官方的写法,也可以使用require.ensure写法。需要注意的是:1 组件的写法不用变化 2 目前不支持动态载入组件。
~~~
let index = ()=>import('@/views/index')
let index = resolve=>require(['@/views/index'],resolve)
let index = 
~~~
当然 标准的写法还是require.ensure ,参考:[代码分割ensure写法](http://www.css88.com/doc/webpack2/guides/code-splitting-require/)
示例如下:
~~~
require.ensure(dependencies: String[], callback: function(require), chunkName: String)
let index = ( )=>require.ensure([],() => r(require('../page/home')), 'home');
~~~
如果需要把某些文件打包到一个文件中,可以通过,需要webpack 2.4以上的版本呢支持才可以。
~~~
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
~~~
### 权限路由
权限路由是指针对路由部分,前端写成全部路由,但是在前端菜单渲染的时候,写成根据接口数据进行匹配的部分,然后进行菜单过滤,最终只得到匹配的部分。这个匹配的关键字可以是路径,name,或者权限点,不包含这个权限点的可以不用显示。(权限点可以设置到meta信息中)
特别备注:有些时候权限是分子集的,路由也分子路由,当我们针对某些父路由,也需要设置默认一个组件,但这样会与我们设置子路由组件时冲突的,那么此时我们是一般设置父路由默认进入一个子路由,然后其默认进入的子路由,地址设置为空。代码如下:
~~~
	{
		path: '/report',
		name: 'report',
		meta:{},
		component: viewloader('reportlist'),
		children:[
			{
			path:'',
			name:'reportlist',
			meta:{},
			component: viewloader('reportList'),
			},
			{
				path:'',
				name:'reportDetail',
				meta:{},
				component: viewloader('reportDetail'),
			}
		]
	},
~~~
当然你也可以设置一个默认的面板 ,这个面板可以展示一些公共内容,包含其他子路由的入口。
~~~
	{
		path: '/report',
		name: 'report',
		meta:{},
		component: viewloader('reportDefault'),
		children:[
			{
			path:'list',
			name:'reportlist',
			meta:{},
			component: viewloader('reportList'),
			},
			{
				path:'',
				name:'reportDetail',
				meta:{},
				component: viewloader('reportDetail'),
			}
		]
	},
~~~
**深入思考 :** 关于权限的部分,我们肯定希望其是固定的并且是更新的,固定的可以用vuex或者web storage实现,把菜单的数据保存下,保证刷新或者切换时路由信息不会丢失;更新的则是用户在登录或者及时性很强的操作中,需要及时的替换去菜单部分数据,保证最新。
### 路由优先级 
如果一个地址可以匹配多个路由,谁先定义的,谁的优先级就高,这也解释了为什么我们的404匹配路由要写在最后。
### 高阶路由 
vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的 [文档](https://github.com/pillarjs/path-to-regexp#parameters) 学习高阶的路径匹配,还有 这个例子  展示 vue-router 怎么使用这类匹配。
### 多业务路由
如果你有多层的路由,都维护在一个router文件肯定是不方便的,建议你将他们维护在多个业务的路由模块,具体写法如下:
~~~
//router/index.js
import system from './system'
import customer from './customer'
const routes = [...system,...customer,...defaultRouters]
//router/system.js
export default [
{
    path:'',
    name:'',
    component:''
    meta:{},
    children:[],
}
]
~~~
### 路由钩子函数
在路由的钩子函数中,我们处理一些效果,进行一些拦截,下面举例说明:
核心语法 :
~~~
//全局前置钩子
router.beforeEach((to, from, next) => {
  // ...
})
//全局置后钩子
router.afterEach((to, from) => {
  // ...
})
// 2.2之后新增路由更新操作
~~~
备注 :如果觉得我就某些页面写钩子太麻烦,你也可以在路由里直接定义好路由部分对应的钩子函数执行对应的操作。
~~~
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
~~~
- 登录拦截
- 非关键页面拦截
- 携带页面位置信息
- 加载动画
- 
### 组件内的导航守卫
也可以直接在组件里定义好自己的导航守卫,做一些高级的程序条件鉴定。
~~~
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`
  }
}
~~~
### 完整的导航解析过程
1. 导航被触发。
2. 在失活的组件里调用离开守卫。
3. 调用全局的 beforeEach 守卫。
4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
5. 在路由配置里调用 beforeEnter。
6. 解析异步路由组件。
7. 在被激活的组件里调用 beforeRouteEnter。
8. 调用全局的 beforeResolve 守卫 (2.5+)。
9. 导航被确认。
10. 调用全局的 afterEach 钩子。
11. 触发 DOM 更新。
12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
### 同一组件渲染
### 路由元信息 
定义路由的时候可以定义meta字段 
~~~
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})
~~~
它的访问时这样的:直接路由中匹配到的路由.meta.keyname .
- 拓展:既然是这样,可能有什么作用呢?
> 1 基于登录的判断,你可以设置一个字段用来决定这个页面是否需要登录访问
> 2 基于刷新的判断,也许你很多组件都用了keep-alive的特性,对于有些页面你不想使用,可以定义一个字段区分
> 3 定义或者使用一些初始化字段,或者页面初始化信息,属于全局比较公用的一些,不想每个页面都去维护
> 4 其他自定义的需求字段都是可以加的,自由发挥,作为一种解决方案可以实现很多你想做的个性需求。
### 加载动画
### 加载优化
### 保持数据
### 运行模式
## 路由传参
## 文档
                    
        - 前端工程化
 - 架构总纲
 - 001
 - 美团技术架构
 - 前端工程化说明
 - 历史背景说明
 - 架构说明
 - 前端工程化技术栈
 - 技术文档说明
 - 功能模块说明
 - 前端模块管理器简介
 - 框架对比分析
 - vue&react&ng对比分析(一)
 - vue&react&ng对比分析(二)
 - vue&react&ng对比分析(三)
 - 工程化专题系列
 - 需要解决的问题
 - 001
 - 002
 - 003
 - 常见代码错误
 - jslint中常见的错误
 - css规范常见错误
 - html规范常见错误
 - 工程化目录
 - 工程化初始化
 - 项目构建流程
 - 项目打包优化
 - 上线与迭代注意事项
 - 前端部署发布
 - jetkins部署
 - 部署需求整理
 - 前端监控
 - 工程化实践指南
 - dock持续部署
 - 系列文章
 - 插拔式前端的设计
 - 其他实践
 - 工程化的前端管理
 - 宋小菜借鉴
 - 大前端团队介绍
 - 人员组成
 - 人员发展
 - 研发流程
 - 任务分类
 - 前端基础建设与架构
 - 技术栈以及技术方案
 - 业务目录大纲
 - 前端大纲
 - api管理
 - 后端api工具
 - 前端easymock
 - api拦截与代理
 - api优化
 - api请求时长策略设计
 - 前端架构专题
 - 架构专题一
 - 产品原型对接
 - 与ui对接
 - 图片专题
 - 图片工程化大纲
 - 图片优化
 - 图标字体
 - 图标字体vs雪碧图
 - 工程化的前端矩阵
 - 蚂蚁金服前端矩阵分享
 - BFF架构
 - 概念解析
 - 前端脚手架
 - 初始化项目
 - 个性化配置
 - 部署与发布
 - 性能优化专题
 - http专题
 - https常识
 - http优化1
 - http优化2
 - http优化3
 - http缓存
 - 常规web性能优化攻略
 - 性能优化大纲
 - 样式优化
 - js优化
 - 第三方依赖优化
 - 代码分割优化
 - 图片优化
 - 打包优化
 - 服务器优化
 - 缓存优化
 - 交互优化
 - pc事件优化
 - 手机事件优化
 - 推荐文章
 - 01
 - 前端安全专题
 - 前端安全大纲
 - 前端第三方库
 - seo优化
 - web框架的对比
 - 001
 - 学习资源
 - 珠峰前端架构
 - npm教程
 - npm入门
 - cnpm入门
 - cnpm搭建
 - 你该知道的js模块
 - browserSync
 - opn
 - js-cookie
 - npm-script进阶
 - 入门篇
 - 进阶篇
 - 高阶篇
 - 实践篇
 - yarn入门
 - nodejs教程
 - axios&&fetch
 - xhr
 - axios
 - fetch
 - babel专题
 - babel入门
 - profill入门
 - nodejs入门
 - 快速入门
 - 大纲介绍
 - node基础
 - global obj
 - assert断言
 - procss-进程
 - child_process子进程
 - cluster集群
 - console控制台
 - crypto-加密
 - dgram-数据报
 - dns-域名服务器
 - error-异常
 - events-事件
 - global-全局变量
 - http-基本协议
 - https-安全协议
 - modules-模块
 - os-操作系统
 - path-路径
 - querystring-查询字符串
 - readline-逐行读取
 - fs-文件系统
 - net-网络操作
 - 命令行工具
 - 内存泄露
 - 代码的组织与部署
 - 异步编程
 - orm模块
 - 异步编程解决方案
 - node-lessons
 - 环境准备
 - nodejs实践
 - 项目搭建
 - 异步优化
 - 创建web和tcp服务器
 - 终端问答程序
 - 爬虫系统
 - mongleDb
 - mongoDB简介
 - 基本使用
 - 实用技巧
 - 汇总001
 - 饿了么后台搭建
 - nodejs干货
 - 沪江基于node的实践
 - 苏宁基于nodejs优化
 - 基于nodejs开发脚手架
 - 书籍干货
 - 深入浅出nodejs
 - 异步I/O(一)
 - gulp教程
 - gulp入门
 - gulp常用插件(1)
 - gulp常用插件(2)
 - gulp创建目录
 - 经验普及贴
 - webpack教程
 - webpack入门
 - 简单入门
 - entry配置
 - output配置
 - 插件使用01
 - 插件使用02
 - loader使用
 - dev-server介绍
 - 构建css
 - css模块化
 - 使用less和sass
 - 构建图片
 - 引入字体
 - babel配置攻略
 - eslint
 - 001
 - webpack进阶
 - 分不同文件检出
 - 优化打包大小
 - 优化打包速度
 - 自定义配置
 - 单页以及多页如何配置
 - 优化实践
 - 文章导读
 - 001
 - 优化指南
 - 参考列表
 - webpack4
 - 多入口程序构建
 - 参考教程
 - 项目实践
 - 环境区分
 - 常见问题
 - 解读webpack
 - 从vuejs权威指南中解决
 - 深入浅出webpack
 - rollup
 - 入门
 - parcel
 - 入门篇
 - express教程
 - nuxt教程
 - 入门
 - 基本入门
 - koa教程
 - koa基本入门
 - koa开发注意事项
 - koa实践指南
 - 关于路由
 - koa优化指南
 - 001
 - Vuejs
 - vuejs入门系列
 - vue-cli入门
 - vue2基本认识
 - vuejs入门教程
 - 样式绑定
 - vuex入门学习笔记
 - vue组件生命周期
 - 组件的使用
 - vue-router入门
 - vue-filter
 - 计算属性使用
 - 开发注意事项
 - mixins
 - 组件通讯
 - vuejs进阶
 - 进阶资源
 - router进阶
 - 官网介绍
 - 前进与后退优化
 - keep-alive基本使用
 - keep-alive原理详解
 - 钩子函数进阶
 - 计算属性&监听&方法
 - vue服务端渲染技术
 - 项目实践之路
 - 实践大纲
 - 插槽专题篇
 - vue-cli升级
 - 进阶入门
 - vuejs架构
 - nuxt
 - vuejs项目实践
 - vue实践常见问题
 - 001
 - 002
 - 003
 - 004
 - 005
 - 改造api参数探索
 - 007
 - 008
 - 009
 - 010
 - 项目技术栈
 - vue性能问题以及优化方案
 - vue-spa应用的理解
 - vue-ssr的部署与使用
 - 滴滴出行实践案例
 - 2.0重构
 - vue-element-admin实践
 - 准备工作
 - 菜单设计
 - 权限设计
 - 依赖模块
 - vue-betterScroll
 - 性能优化懒加载
 - 京东组件实践
 - vue2项目小结
 - vue探索与实践
 - 去哪实践
 - 介绍
 - 饿了么项目实践
 - 项目解析
 - vue骨架屏实践
 - vue生态推荐
 - ui框架
 - elementUI
 - 001
 - 002
 - VUE-material
 - vant-ui
 - 解读入门
 - iview
 - 使用问题汇总
 - vux
 - mint-ui
 - loadmore
 - vue资源导航
 - vueconf
 - 源码解读
 - vm
 - 双向绑定
 - 基本原理
 - 数组双向绑定
 - 报错机制
 - 封装方法
 - 运行环境
 - 入门
 - 指令
 - vue-router解读
 - util
 - vue-props
 - 流程逻辑
 - 推荐文章
 - 源码解读
 - 文章导读
 - 001
 - vuejs实战
 - 基础篇
 - 进阶篇
 - 实践篇
 - 面试专题
 - angularjs教程
 - angularjs入门系列
 - 基本入门
 - ng2入门
 - ng进阶
 - ng项目实践
 - 源码解读
 - typescript
 - reactjs教程
 - reactjs入门系列
 - react的基本入门
 - react组件
 - virtalDom认识
 - react-cli入门
 - react组件的生命周期
 - 基本知识点
 - react-router教程
 - react进阶
 - 基本实践
 - react加载性能优化指南
 - react属性封装
 - 进阶45讲
 - 01概述
 - 02jsx
 - 06高阶组件&函数子组件
 - contextApi
 - react-router
 - 入门章节
 - 进阶
 - 高阶组件
 - react进阶组件
 - 基本介绍
 - render props
 - render props的封装
 - render props getter
 - react-native入门
 - 源码解读
 - 001
 - 002-reactDemo
 - 参考教程
 - 参考教程1
 - 了解react-hooks
 - ui框架
 - pc端ui框架推荐
 - 项目实践
 - weatherApp
 - 001
 - 002
 - 不同生命周期使用场景
 - react项目结构和组件的命名
 - 常见问题解答
 - 参考书籍
 - react全栈
 - 前言
 - react与redux进阶
 - 常见误解
 - 反模式
 - react设计模式与最佳实践
 - 7美化组件
 - 7.2行内样式
 - 7.4css模块
 - 深入react技术栈
 - react学习手册
 - 序
 - mobx教程
 - 入门
 - 大佬推荐
 - 001
 - react面试
 - 001
 - linux教程
 - linux入门
 - 基本入门
 - 文件管理
 - 文件传输
 - 文档编辑
 - 磁盘管理
 - 磁盘维护
 - 网络通讯
 - 系统管理
 - 系统设置
 - 备份压缩
 - 设备管理
 - 查看系统信息
 - linux其他
 - webhook
 - rsync入门教程
 - ssh免登陆设置
 - 安装nodejs
 - nginx教程
 - 入门教程
 - 安装
 - 基本配置
 - 服务基本使用
 - 高性能nginx
 - 001
 - pm2教程
 - shell教程
 - 入门大纲
 - echo命令
 - 参考文献
 - linux常用命令2
 - linux常见问题
 - 001
 - python
 - 入门教程
 - 机器学习
 - 准备工作
 - 服务器常识
 - tomcat
 - 入门常识
 - iis
 - redis教程
 - 入门第一篇
 - redis进阶
 - 项目实践
 - redis使用问题
 - mongleDB
 - 入门
 - 使用进阶
 - 项目实践
 - 常见问题
 - electron
 - 入门系列
 - 前言
 - 小程序
 - 入门
 - 准备工作
 - 路由
 - 参考文档
 - 001
 - 小程序开发--双路视频调研
 - 准备工作
 - 参考资源
 - 参考网址
 - docker
 - 入门
 - 基本认识
 - 安装与使用
 - docker安装nginx
 - docker安装jetkins(1)
 - docker部署jenkins(2)
 - 进阶
 - 实践总结
 - docker群分享
 - docker部署前端应用
 - 文章导读
 - docker其他
 - 网络安全
 - 入门
 - 大纲
 - 项目解析
 - schoolpal.web
 - 功能模块大纲
 - 目录结构大纲
 - 前端国际化
 - 国际化方案
 - 其他
 - bower入门教程
 - weex
 - 入门
 - memcached
 - 入门
 - sails
 - 入门
 
