参考:https://router.vuejs.org/zh-cn/

安装

  • 直接下载 / CDN

https://unpkg.com/vue-router/dist/vue-router.js

使用:

<script src="/path/to/vue.js"></script>

<script src="/path/to/vue-router.js"></script>

  • NPM

npm install vue-router

使用:

import Vue from 'vue'

import VueRouter from 'vue-router'

Vue.use(VueRouter)

使用:

  • 动态路由匹配

  例子:

const User = {
  template: '<div>User</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

/user/foo 和 /user/bar 都将映射到相同的路由

一个『路径参数』使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用

模式 匹配路径 $route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: 123 }

  响应路由参数的变化

  从 /user/foo 导航到 user/bar,原来的组件实例会被复用 , 意味着组件的生命周期钩子不会再被调用

  复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch(监测变化) $route 对象

  watch: { '$route' (to, from) { // 对路由变化作出响应... } }

  匹配优先级

    有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高

嵌套路由

  例子:

    export default new Router({

      routes: [

     {
      path: '/',//设置默认根页面
        redirect: '/recommend'
     },

{
  path: '/recommend',
  component: component:require('../pages/login-common/login'),
  children: [
    {
      path: ':id',
      component: '组件'
    }
  ]
}

      ]
    })

编程式的导航

使用:

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
router.push(location) 点击 <router-link :to="..."> 等同于调用router.push(...)
方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL

参数:

  router.push('home')   // 字符串

  router.push({ path: 'home' })  // 对象

  router.push({ name: 'user', params: { userId: 123 }})  // 命名的路由

  router.push({ path: 'register', query: { plan: 'private' }})  // 带查询参数,变成 /register?plan=private

router.replace(location):

  跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录

  <router-link :to="..." replace>     ==    router.replace(...)

router.go(n) : 

  // 在浏览器记录中前进一步,等同于 history.forward()

  router.go(1)

  // 后退一步记录,等同于 history.back()

  router.go(-1)

命名视图

想同时(同级)展示多个视图,而不是嵌套展示 , 命名视图就派上用场了 , 如果 router-view 没有设置名字,那么默认为 default

例子:

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

确保正确使用 components 配置(带上 s):

const router = new VueRouter({
  routes: [{
    path: '/',
    components: {

      default: Foo,

      a: Bar,

      b: Baz

    }
  }]
})

导航钩子

vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的

  • 全局钩子有三个,分别是beforeEach、beforeResolve和afterEach,在路由实例对象注册使用

beforeEach:

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => { })
三个参数:
  to: Route: 即将要进入的目标 路由对象
  from: Route: 当前导航正要离开的路由
  next: Function: 执行效果依赖 next 方法的调用参数
    next(): 进行管道中的下一个钩子
    next(false): 中断当前的导航
    next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航
确保要调用 next 方法,否则钩子就不会被 resolved

afterEach:

  不像 before 钩子那样,after 钩子没有 next 方法,不能改变导航

例子:

router.beforeEach((to,from,next)=>{
  console.log('global beforeEach')
  next();
});

router.beforeResolve((to,from,next)=>{
  console.log('global beforeResolve')
  next();
});

router.afterEach((to,from,next)=>{
  console.log('global afterEach')
});

  • 某个路由独享的钩子 beforeEnter

  在路由配置上直接定义 beforeEnter 钩子

const router = new VueRouter({
  routes: [{
    path: '/foo',
    component: Foo,
    beforeEnter: (to, from, next) => {}
  }]
})

  • 组件内的钩子

    • beforeRouteEnter
    • beforeRouteUpdate (2.2 新增)
    • beforeRouteLeave

beforeRouteEnter (to, from, next) {
  // 在渲染该组件的对应路由被 confirm 前调用
  // 不!能!获取组件实例 `this`, 因为当钩子执行前,组件实例还没被创建
  //传一个回调给 next来访问组件实例
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
},

beforeRouteUpdate (to, from, next) {
  // 在当前路由改变,但是该组件被复用时调用
  // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
  // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  // 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
  // 导航离开该组件的对应路由时调用

  //beforeRouteLeave 中直接访问 this。这个 leave 钩子通常用来禁止用户在还未保存修改前突然离开。可以通过 next(false) 来取消导航
}

  • 执行时机

由首页进入user页面:

global beforeEach > router beforeEnter > component beforeRouteEnter > global beforeResolve > global afterEach > mounted

由user回到首页:

component beforeRouteLeave => global beforeEach => global beforeResolve => global afterEach

排除beforeRouteUpdate,其余六个导航钩子的执行时机其实很好理解。大体按照leave、before、enter、resolve、after的顺序并全局优先的思路执行。beforeRouteUpdate的触发是在动态路由情形下,比如 path: '/user/:userName' 这条路由,当页面不变更只动态的改变参数userName时,beforeRouteUpdate便会触发

  • 总结:

使用vue组件拼凑成整个应用,每个页面是独立的,路由依靠链接跳转,会刷新页面。使用vue-router则可以不刷新页面加载对应组件,hash和history模式模拟路径变化,不刷新页面

数据获取

导航完成之后获取:

  先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示

  created () {

    // 组件创建完后获取数据,此时 data 已经被 observed 了

    // 基于 $route.params.id 获取文章数据

    fetchData();

  },

  watch: {

    // 如果路由有变化,会再次执行该方法

    '$route': 'fetchData'

  },

导航完成之前获取:

  导航完成前,在路由的 enter 钩子中获取数据,在数据获取成功后执行导航

beforeRouteEnter (to, from, next) {
  getPost(to.params.id, (err, post) =>
    if (err) {
      next(false)
    } else {
      next(vm => {vm.post = post })
    }
  })
},

路由懒加载

打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了

Vue 的 异步组件 和 Webpack 的 code splitting feature , 实现路由组件的懒加载

const Foo = resolve => {
  // require.ensure 是 Webpack 的特殊语法,用来设置 code-split point
  require.ensure(['./Foo.vue'], () => {
    resolve(require('./Foo.vue'))
  })
}

使用 AMD 风格的 require , 实现路由组件的懒加载

  const Foo = resolve => require(['./Foo.vue'], resolve)

使用 es6 风格的 import, 实现路由组件的懒加载

const Recommend = (resolve) => {
  import('components/recommend/recommend').then((module) => {
    resolve(module)
  })
}

API

  • <router-link>

  支持用户在具有路由功能的应用中(点击)导航, 默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属性生成别的标签 ,

  目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名

to :

被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象
<router-link to="home">Home</router-link>         <!-- 字符串 -->
<router-link v-bind:to="'home'">Home</router-link>    <!-- 使用 v-bind 的 JS 表达式 -->
<router-link :to="'home'">Home</router-link>      <!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="{ path: 'home' }">Home</router-link>
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>     <!-- 命名的路由 -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link> <!-- 结果为 /register?plan=private -->

relpace :

  调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录

append :

设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>

tag :

默认值: "a"
<router-link to="/foo" tag="li">foo</router-link>
<li>foo</li><!-- 渲染结果 -->

active-class :

类型: string
默认值:"router-link-active"
设置 链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置

events:

类型: string | Array<string>
默认值:'click'
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组

将"激活时的CSS类名"应用在外层元素:

我们要让 "激活时的CSS类名" 应用在外层元素,而不是 <a> 标签本身,那么可以用 <router-link> 渲染外层元素,包裹着内层的原生 <a> 标签:
<router-link tag="li" to="/foo">
  <a>/foo</a>
</router-link>
在这种情况下,<a> 将作为真实的链接(它会获得正确的 href 的),而 "激活时的CSS类名" 则设置到外层的<li> 

  • <router-view>

渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件

属性 name:   类型: string ;  默认值: "default"

如果 <router-view>设置了名称,则会渲染对应的路由配置中 components 下的相应组件

可以配合 <transition> 和 <keep-alive> 使用 ,确保在内层使用 <keep-alive>
<transition>
  <keep-alive>
    <router-view></router-view>
  </keep-alive>
</transition

路由信息对象

route object(路由信息对象) 表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route records(路由记录)

route object 是 immutable(不可变) 的,每次成功的导航后都会产生一个新的对象

route object 出现在多个地方:

    • 组件内的 this.$route 和 $route watcher 回调(监测变化处理);
    • router.match(location) 的返回值
    • 导航钩子的参数:

  router.beforeEach((to, from, next) => {
    // to 和 from 都是 路由信息对象
  })

路由信息对象的属性

    • $route.path

    类型: string
    解析为绝对路径 : 如 "/foo/bar"。

    • $route.params

    类型: Object
    一个 key/value 对象,包含了 动态片段 和 全匹配片段,如果没有路由参数,就是一个空对象。

    • $route.query

    类型: Object
    一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。

    • $route.hash

    类型: string
    当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。

    • $route.fullPath

    类型: string
    完成解析后的 URL,包含查询参数和 hash 的完整路径。

    • $route.matched

    类型: Array<RouteRecord>
    一个数组,包含当前路由的所有嵌套路径片段的 路由记录 。路由记录就是 routes 配置数组中的对象副本(还有在 children 数组)。

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          children: [
            { path: 'bar', component: Bar }
          ]
        }
      ]
    })

    当 URL 为 /foo/bar,$route.matched 将会是一个包含从上到下的所有对象(副本)。

    • $route.name

    当前路由的名称,如果有的话。(查看 命名路由)

(生产)vue-router:路由的更多相关文章

  1. 前端MVC Vue2学习总结(八)——Vue Router路由、Vuex状态管理、Element-UI

    一.Vue Router路由 二.Vuex状态管理 三.Element-UI Element-UI是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,手机端有对应框架是 Mint U ...

  2. Vue系列:Vue Router 路由梳理

    Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌.包含的功能有: 嵌套的路由/视图表 模块化的.基于组件的路由配置 路由参数. ...

  3. 04 Vue Router路由管理器

    路由的基本概念与原理 Vue Router Vue Router (官网: https://router.vuejs.org/zh/)是Vue.js 官方的路由管理器. 它和vue.js的核心深度集成 ...

  4. Vue Router路由管理器介绍

    参考博客:https://www.cnblogs.com/avon/p/5943008.html 安装介绍:Vue Router 版本说明 对于 TypeScript 用户来说,vue-router@ ...

  5. Vue Router 路由守卫:完整的导航解析流程

    完整的导航解析流程 1 导航被触发. 2 在失活的组件里调用离开守卫. 3 调用全局的 beforeEach 守卫. 4 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+). ...

  6. Vue Router路由守卫妙用:异步获取数据成功后再进行路由跳转并传递数据,失败则不进行跳转

    问题引入 试想这样一个业务场景: 在用户输入数据,点击提交按钮后,这时发起了ajax请求,如果请求成功, 则跳转到详情页面并展示详情数据,失败则不跳转到详情页面,只是在当前页面给出错误消息. 难点所在 ...

  7. Vue Router 路由实现原理

    一.概念 通过改变 URL,在不重新请求页面的情况下,更新页面视图. 二.实现方式 更新视图但不重新请求页面,是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要有2种方式: 1.Hash  ...

  8. Vue - Router 路由

    路由的注册 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  9. vue router路由(三)

    当环境搭建及Vue语法与指令都有所了解,该说下router. build目录是打包配置文件 (不建议动) config是vue项目基本配置文件 dist是构建后文件 js 手动创建 (根据需要) no ...

  10. vue router路由跳转了,但是页面没有变(已解决)

    小白学习 router.js:两个组件之间跳转 但是路由变了,页面没有改变的原因是因为app.vue里面没有router-view(很关键)

随机推荐

  1. Linux之rsync数据同步服务

    rsync是一个开源.快速的.多动能的.可以实现全量,增量的本地或远程数据同步备份工具,它适用于多种操作系统平台. 1.rsync的特性(功能) (1)支持拷贝特殊文件(如链接文件.设备文件) (2) ...

  2. C语言数据结构-栈的实现-初始化、销毁、长度、取栈顶元素、查找、入栈、出栈、显示操作

    1.数据结构-栈的实现-C语言 #define MAXSIZE 100 //栈的存储结构 typedef struct { int* base; //栈底指针 int* top; //栈顶指针 int ...

  3. CF580B Kefa and Company 尺取法

    Kefa wants to celebrate his first big salary by going to restaurant. However, he needs company. Kefa ...

  4. maven 设置 编码 ,jdk 版本

    <profile> <id>jdk1.8</id> <activation> <activeByDefault>true</activ ...

  5. mongodb 基础语法

    参考原文:菜鸟教程 目录 一.数据库二.文档三.索引四.聚合 一.数据库 show dbs -- 查看所有数据库 use DATABASE_NAME -- 如果数据库不存在,则创建数据库,否则切换到指 ...

  6. hutool http+天气预报

    中国天气接口:http://www.weather.com.cn/data/sk/地址.html,只显示当天. sojson接口:http://t.weather.sojson.com/api/wea ...

  7. Why Nexiq 125032 USB Link Truck diagnostic tool is so helpful ?

    As for as I am concerned , Heavy Duty Diagnostic Nexiq 125032 USB is a helpful tool , which has exce ...

  8. my.资质

    换算到每1点魔力初始,1点魔力等同于22点法资,等于0.00235点成长. 气血=等级*体力资质*0.002895+体力属性点*成长*7 魔法=等级*法力资质*0.002085+法力属性点*成长*5 ...

  9. 转 dango的模型总结 and django-关于manage.py migrate无效的问题

    http://iluoxuan.iteye.com/blog/1703061 1:用过django就知道django的model有多方便: 首先介绍下django的模型有哪些属性:先看例子: Djan ...

  10. Trees on the level UVA - 122 (二叉树的层次遍历)

    题目链接:https://vjudge.net/problem/UVA-122 题目大意:输入一颗二叉树,你的任务是按从上到下,从左到右的顺序输出各个结点的值.每个结点都按照从根节点到它的移动序列给出 ...