vue2.0-路由

简介

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转;

  route:首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;

  routes:它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合;

  router:译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;


vue路由模式

Vue路由模式有hash模式,使用URL的hash值来作为路由,支持所有浏览器;history模式,依赖于HTML5 API(旧浏览器不支持)和HTTP服务端配置;abstract模式,适用于所有JavaScript环境。
Vue 路由是指根据 url 分配到对应的处理程序;作用就是解析 URL,调用对应的控制器(的方法,并传递参数)。Vue 路由有助于在浏览器的 URL 或历史记录与 Vue 组件之间建立链接,从而允许某些路径渲染与之关联的任何一个视图。那么 vue 路由模式有哪些呢?
1.hash 模式
使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,其显示的网路路径中会有 “#” 号,有一点点丑。这是最安全的模式,因为他兼容所有的浏览器和服务器。
2.history 模式
美化后的 hash 模式,会去掉路径中的 “#”。依赖于 Html5 的 history,pushState API,所以要担心 IE9 以及一下的版本,感觉不用担心。并且还包括 back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作。
但是 history 也是有缺点的,不怕前进后退跳转,就怕刷新(如果后端没有准备的话),因为刷新是实实在在地去请求服务器了。
3.abstract 路由模式
abstract 是 vue 路由中的第三种模式,本身是用来在不支持浏览器 API 的环境中,充当 fallback,而不论是 hash 还是 history 模式都会对浏览器上的 url 产生作用,本文要实现的功能就是在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由 path,这就利用到了 abstract 这种与浏览器分离的路由模式。
总结:vue 路由模式有 hash 模式,使用 URL 的 hash 值来作为路由,支持所有浏览器;其 url 路径会出现“#”字符;history 模式,依赖于 HTML5 API(旧浏览器不支持)和 HTTP 服务端配置,没有后台配置的话,页面刷新时会出现 404;abstract 模式,适用于所有 JavaScript 环境,如果没有浏览器 API,路由器将自动被强制进入此模式。
在传统的 web 开发中每一个请求地址都会请求服务器来进行处理,但是用户有些操作则无需请求服务器,直接页面端修改下逻辑就能达到目的,在这种方式下最好的方法是使用路由,因为使用路由时,URL 会随着改变,用户浏览一个网页时可以直接复制或收藏当前页面的 URL 给别人,这种方式对于搜索引擎和用户来说都是友好的

路由创建

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = []
const router = new VueRouter({
 mode: 'hash',
 base: process.env.BASE_URL,
 routes
})
export default router

完整的路由解析流程

导航被触发。

在失活的组件里调用 beforeRouteLeave 守卫。

调用全局的 beforeEach 守卫。

在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。

在路由配置里调用 beforeEnter。

解析异步路由组件。

在被激活的组件里调用 beforeRouteEnter。

调用全局的 beforeResolve 守卫 (2.5+)。

导航被确认。

调用全局的 afterEach 钩子。

触发 DOM 更新。

调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

路由守卫

每个守卫方法接收三个参数:

to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。

next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

全局路由守卫

- 全局前置守卫 beforeEach

你可以使用 router.beforeEach 注册一个全局前置守卫:

  const router = new VueRouter({ ... })
  router.beforeEach(async(to, from, next) => {
    const hasToken = getToken()
    if (hasToken) {
      if (to.path === '/login') {
        next({ path: '/' })
      } else {
        const hasGetUserInfo = store.getters.name
        if (hasGetUserInfo) {
          next()
        } else {
          try {
            await store.dispatch('user/getInfo')
            next()
          } catch (error) {
            await store.dispatch('user/resetToken')
            next(`/login?redirect=${to.path}`)
          }
        }
      }
    } else {
      if (whiteList.indexOf(to.path) !== -1) {
        next()
      } else {
        next(`/login?redirect=${to.path}`)
      }
    }
  })

- 全局解析守卫 afterEach

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

  router.afterEach((to, from) => {
    // ...
  })

- 路由独享的守卫

你可以在路由配置上直接定义 beforeEnter 守卫:

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

局部路由守卫

- beforeRouteEnter

  beforeRouteEnter(to, from, next) {
      // 不!能!获取组件实例 `this`
      // 因为当守卫执行前,组件实例还没被创建
      //解决:
      next(vm => {
      // 通过 `vm` 访问组件实例
    })
    },

- beforeRouteUpdate

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

- beforeRouteLeave

  beforeRouteLeave(to, from, next) {
      // 导航离开该组件的对应路由时调用
      // 可以访问组件实例 `this`
    }

动态路由

router.addRout(routes)

路由元信息

定义路由的时候可以配置 meta 字段:

  const router = new VueRouter({
    routes: [
      {
        path: '/foo',
        component: Foo,
        children: [
          {
            path: 'bar',
            component: Bar,
            // a meta field
            meta: { requiresAuth: true }
          }
        ]
      }
    ]
  })
 // 一个路由匹配到的所有路由记录会暴露为 $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()
    }
  })

路由懒加载

- 异步组件懒加载webpack

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

  //结合 Vue 的异步组件 和 Webpack 的代码分割功能 ,轻松实现路由组件的懒加载。
  //有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。
  const router = new VueRouter({
  routes: [{ path: '/foo', component: () => import('./Foo.vue')
  }]
  })
  或
  component: resolve=>(require(["@/components/HelloWorld"],resolve)) } ] })
  
  //2. 组件懒加载方案三: webpack提供的require.ensure() */
  {
    path: '/home',
    name: 'home',
    component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
  },

异步加载

vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .

但是,这种情况下一个组件生成一个js文件

 /* vue异步组件技术 */
  { path: '/home', name: 'home', component: resolve => require(['@/components/home'],resolve) },

路由的过渡

  //单个路由的过渡
  //上面的用法会给所有路由设置一样的过渡效果,如果你想让每个路由组件有各自的过渡效果,可以在各路由组件内使用  并设置不同的 name。
  const Foo = {
    template: `
      
        
...
` } const Bar = { template: `
...
` } //基于路由的动态过渡 //还可以基于当前路由与目标路由的变化关系,动态设置过渡效果: // 接着在父组件内 // watch $route 决定使用哪种过渡 watch: { '$route' (to, from) { const toDepth = to.path.split('/').length const fromDepth = from.path.split('/').length this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' } }

路由跳转

路由参数

什么是: 从上一个页面组件跳转到下一个页面组件时,顺便携带参数值到下一个页面组件,继续使用!

params参数类型:

 //1.修改路由字典中的路由记录对象: 
 var routes=[
        ... ...
        {path:"/details/:自定义变量名", component: Details , props:true}
    ]
  // params传参数(类似post) 路由配置 path: "/home/:id" 或者 path: "/home:id"
  // 配置path,刷新页面id会保留 -- 不配置path,第一次可请求,刷新页面id会消失
跳转方式:下面使用的是借用name跳也可使用path
  //1.push: 追加历史记录,即在前一条的记录上在新加一条浏览记录
  //2.replace: 覆盖历史记录,即在添加新记录的同时回收原有记录,替换掉原有记录
  // html 取参:$route.params.id -- script取参: this.$route.params.id
  
  this.$router.push({name:'home',params: {id:'1'}})
  this.$router.replace({name:'home',params: {id:'1'}})
  

query参数类型:

// query传参数 (类似get,url后面会显示参数) 路由可不配置 

跳转方式:下面使用的是借用name跳也可使用path
//1.push: 追加历史记录,即在前一条的记录上在新加一条浏览记录
//2.replace: 覆盖历史记录,即在添加新记录的同时回收原有记录,替换掉原有记录
// html取参:$route.query.id -- script取参:this.$route.query.id
 
// 
this.$router.push({name:'home',query: {id:'1'}})
//this.$router.push({path:'/home',query: {id:'1'}})
this.$router.replace({name:'home',query: {id:'1'}})
//this.$router.replace({ path:'/home',query: {id:'1'} })

其它路由方法

- go
  this. $router.go(1) //前进一步 相当于history.forward()
  
  this. $router.go(-1) //后退一步 相当于history.back()
  
  this. $router.go(10)
- back后退

- forward前进

  useRouter 获取到当前router对象的方法
  router.addRoute 添加路由(vue2.0)
  router.removeRoute(‘login’) 删除指定路由
  router.hasRoute 查询是否由指定的路由
  router.getRoutes 返回所有注册路由

注意:

传递对象 (object不能过长,不然会报错:Failed to load resource: the server responded with a status of 400 (Bad Request))

query传递对象 (类似get,url后面会显示参数) JSON.stringify(obj) 转一下

你可能感兴趣的:(vue.js,前端)