学习vue-router

vue-router 基础

  1. 做用: 经过管理URL,实现URL和组件的对应和经过URL进行组件之间的切换
  2. 其余概念:

单页应用:加载单个HTML页面,并在用户与应用程序交互时,动态该页面vue

  1. 使用步骤:vue-router

    • 安装模块: npm install vue-router --savenpm

    • 引入模块: import VueRouter from 'vue-router'编程

    • 做为插件:Vue.use(VueRoter)数组

    • 建立路由实例对象:浏览器

      new VueRouter({
          // 匹配相关参数
      })
      
      复制代码
    • 注入vue选项参数: new VueRouter({ router })bash

    • 告诉路由渲染的位置: 异步

    • 引入组件,匹配组件URL:<router-link v-bind:to="path"> 内容 </router-link>ide

    具体页面代码:函数

    import Vue from 'vue'
    // 1. 安装vue-router后引入vue-router模块
    import Router from 'vue-router'
    import Index from '@/views/index'
    
    // 2. 做为插件
    Vue.use(Router)
    
    // 3. 建立路由实例对象
    export default new Router({
    mode : 'history',// 历史模式
    linkActiveClass: 'is-active', // 活动样式
    scrollBehavior(to, from, savePosition){
        // 点击浏览器的前进后退或切换导航时触发
        console.log(to); // 要进入的目标对象  要去哪
        console.log(from); // 离开的目标  从哪来
        console.log(savePosition); // 记录滚动条位置,点击前进后退时触发
    
        // if(savePosition){
        //   return savePosition; // 滚动条位置不是0时,便可保存位置
        // }else{
        //   return {x:0,y:0} 
        // }
    
        if(to.hash){
        return {
            selector: to.hash
        }
        }
    },
    routes: [
        {
        path: '/',
        name: 'Index',
        component: Index
        }
    ]
    })
    
    
    复制代码

    动态路由匹配

    动态路径参数 以冒号开头

    {
        path:'/user/:id',component: User
    }
    复制代码

    一个“路径参数”使用冒号:标记。当匹配到一个路由时,参数会被设置到this.$route.params,能够在每一个组件内使用。
    也能够在一个路径张红设置多段“路径参数”,对应的值都会设置到$route.params

    • 捕获全部路由或404 Not found路由 {path: '*'}

    当使用了一个通配符时,$route.params内会自动添加一个名为pathMath参数。


编程式的导航

除了使用<router-link></router-link>建立a标签来定义导航连接,还能够经过编写代码来实现。

router.push(location, onComplete?, onAbort?)
注意:在vue实例内部,能够经过$router访问路由实例

想要导航到不一样的URL,则使用router-push方法。这个方法会向history栈添加一个新的记录

该方法的参数能够是一个字符串路径,或者一个描述地址的对象

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

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

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

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

router.replace(location, onComplete?, onAbort?) :替换掉当前的history记录

router.go(n) 在history记录中向前或者后退多少步,相似window.history.go(n)


命名视图

<router-view name='slider'></router-view>
路由视图<router-view>通常的默认命名为default,当想要匹配不一样的视图时,即可以经过命名,找到相应的视图组件。name值的匹配


## 重定向和别名 ``` const router = new VueRouter({ routes: [ {path: '/a', redirect: '/b'} ] }) ``` 或者是动态返回重定向目标:
const router = new VueRouter({
    routes: [
        {path:'/a',redirect: to =>{
            // 方法接收 目标路由 做为参数
            // return 重定向的 字符串路径/路径对象
        }}
    ]
})

复制代码

注意导航守卫并无应用在跳转路由上,而仅仅应用在其目标上。


路由组件传参

在组件中使用$route会使之与其对应路由造成高度耦合,从而使组件只能在某些特定的URL上使用,限制了灵活性。

使用props将组件和路由解耦: 取代与$route的高耦合

const User = {
    template: '<div>User {{ $route.params.id }}</div>'
    }
    const router = new VueRouter({
    routes: [
        { path: '/user/:id', component: User }
    ]
    })
复制代码

经过 props 解耦

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

    // 对于包含命名视图的路由,你必须分别为每一个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

复制代码

三大模式

  • 布尔模式

若是props 被设置为true,route.params将会被设置为组件属性

  • 对象模式

若是props是一个对象,它会被按原样设置为组件属性。当props是静态的时候有用

  • 函数模式

能够建立一个函数返回props。这样就能够将参数转换成另外一种类型,将静态值与基于路由的值结合等。

尽量保持props函数为无状态的,由于它只会在路由发生变化时起做用。若是须要状态来定义props,请使用包装组件,这样vue才能够对状态变化作出反应

导航守卫

组件内的守卫

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`
  }
}

复制代码

注意: beforeRouteEnter守卫不能访问this,由于守卫在导航确认前被调用,所以即将登场的新组件还没被建立。 不过能够经过一个回调next来访问组件实例。在导航被确认的时候执行回调,而且把组件实例做为回调方法的参数:

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 经过 `vm` 访问组件实例
  })
}
复制代码

注意: beforeRouteEnter是支持给next传递回调的惟一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来讲,this 已经可用了,因此不支持传递回调,由于没有必要了

beforeRouteUpdate (to, from, next) {
    // just use `this`
    this.name = to.params.name
    next()
    }

复制代码

这个离开守卫一般用来禁止用户在还未保存修改前忽然离开。该导航能够经过 next(false) 来取消。

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

复制代码

完整的导航解析流程

  1. 导航被触发
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的beforeEach守卫
  4. 在重用的组件里调用beforeRouteUpdate
  5. 在路由配置里调用beforeEnter
  6. 解析异步路由组件
  7. 在被激活的组件里调用beforeRouteEnter
  8. 调用全局的beforeResolve守卫
  9. 导航被确认
  10. 调用全局的afterEach钩子
  11. 触发DOM更新
  12. 用建立好的实例调用beforeRouteEnter守卫中传给next的回调函数

路由元信息

一个路由匹配到的全部路由记录会暴露为$route对象(还有在导航守卫中的路由对象)的$route.matched数组。所以,咱们须要遍历$route.matched来检查路由记录中的meta字段

下面例子展现在全局导航守卫中检查元字段:

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 确保必定要调用 next()
  }
})
复制代码

数据获取

  • 导航完成以后获取:先完成导航,而后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
  • 导航完成以前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

导航完成后获取数据

立刻导航和渲染组件,而后在组件的created钩子中获取数据。获取数据期间会展现loading状态,能够在不一样视图间展现不一样的loading状态。

相关文章
相关标签/搜索