参考: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. window.performance

    利用window.performance查看网页性能 一般我们可以通过浏览器的调试工具-网络面板,或者代理工具查看网页加载过程中的各个阶段的耗时.而利用window.performance属性则可以获 ...

  2. docker 部署net core程序 curl访问地址 提示 Connection reset by peer

    最近研究netcore 部署到docker上.在参考https://www.cnblogs.com/subendong/p/8992285.html教程之后,部署成功.但是curl访问对应的主机端口地 ...

  3. vs 部署SharePoint项目时, package丢失

    bug描述:vs部署sharepoint项目时报错:重启iis应用池失败,未将对象设置引用到实例. 解决方案:查看项目文件(包括隐藏文件),发现package文件不见了,在回收站内能找到被删除的pac ...

  4. 如何查看mysql执行的所有SQL

    在程序调试中,有时需要看到最终在DB执行的SQL文,而默认mysql此功能是关闭的,开启的方法如下: set global general_log='ON'; 然后用如下命令查看log文件所在路径即可 ...

  5. Problem03 水仙花数

    题目:打印出所有的"水仙花数"."水仙花数"是指一个三位数,其各位数字立方和等于该数本身. 例如:153是一个"水仙花数",因为153=1的 ...

  6. Unable to verify your data submission.加入了_csrf也报400错误的解决

    <input type="hidden" name="_csrf" value="<?=Yii::$app->request-> ...

  7. 搭建hadpoot平台(集群式分布)

    1.先下载VMware1.2,然后安装. 2.下载ubuntu-1.4.05-desktop-amd64.iso.下载地址:http://mirrors.aliyun.com/ubuntu-relea ...

  8. docker 安装的centos7.4中无法识别文件中的中文

    在容器内执行命令: 命令: yum -y install kde-l10n-Chinese && yum -y reinstall glibc-common 命令: localedef ...

  9. Maven 错误 Failure to transfer ...was cached in the local repository...

    Maven 错误 Failure to transfer ...was cached in the local repository... 我解决的时候多了两步才解决 1. mvn clean ins ...

  10. derby

    /** * @Title: T.java * @Package test * @Description: TODO please write your description <BR> * ...