参考: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进程切换问题

    #define switch_to(prev,next,last) do { \ unsigned long esi,edi; \ asm volatile("pushfl\n\t" ...

  2. Jenkins+Git+Maven+Nexus+Tomcat

    https://www.jianshu.com/p/d24e64559440 https://blog.csdn.net/u013322876/article/details/72637854 htt ...

  3. 在生产环境下禁用swagger

    学习目标 快速学会使用注解关闭Swagger2,避免接口重复暴露. 使用教程 禁用方法1:使用注解@Profile({"dev","test"}) 表示在开发或 ...

  4. pytorch 0.4.1安装问题

    环境 ubuntu 16.04, anaconda3, python 2.7 将pytorch升级为0.4.1后,import torch报错 undefined symbol: _ZN4thpp10 ...

  5. java 在web应用中获取本地目录和服务器上的目录不一致的问题

    先来讲讲我所遇到的问题.最近有个新的项目添加新的功能. 修改之后部署到服务器上面发现取到classpath目录跑到别的地方去了.在本地测试却正常. 当时毛的着火了.硬是想不懂什么问题. 终于发现了这个 ...

  6. [Leetcode]014. Longest Common Prefix

    public class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.l ...

  7. 最长子序列问题(二分+贪心nlogn算法)

    [题目描述] 给定N个数,求这N个数的最长上升子序列的长度. [样例输入] 7 2 5 3 4 1 7 6 [样例输出] 4 什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段不断严格上升的 ...

  8. Oracle redo undo

    通常对undo有一个误解,认为undo用于数据库物理地恢复到执行语句或事务之前的样子,但实际上并非如此.数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可 ...

  9. linux查找重复文件

    >/dev/ >/dev/null|grep 02a42c7a845094a8904f7b3faf686b81 uniq -d, --repeated only print duplica ...

  10. HTTP.SYS远程代码执行漏洞测试(ms15-034)

    1.HTTP.SYS远程代码执行漏洞简介 首先漏洞编号:CVE-2015-1635(MS15-034 ) 远程执行代码漏洞存在于 HTTP 协议堆栈 (HTTP.sys) 中,当 HTTP.sys 未 ...