# 基本使用

// ../router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from 'routes'
// 注册路由
Vue.use(VueRouter);
export default new VueRouter({
    mode:'history',
    routes
})
--------------
//routes.js 路由表文件
import Home from '../pages/Home'
export default [
    {
        path:'/',
        component:Home
    },
    {
        path:'/',
        redirect:Home // 默认选中 Home 路由组件
    }
]
-----------
//main.js 在全局文件中使用路由器
import Vue from 'vue';
import router from '../Router';
new Vue({
    name:'app',
    eq:'#app',
    components:{
        router
    }
})

当我们在 main.js 中注册了 router ,我们就可以在任何一个组件(包括非路由组件)中使用 $route$router 对象了。

$route 对象是局部路由信息对象,它包含了当前路由组件里的信息,包括 paramsquery 参数等等,我们可以用它来获取路由组件的参数

$router 对象是全局的路由器对象,全局就一个。它包含了很多属性和方法(push、replace、go 等等),可以让整个应用都可以拥有路由功能。编程式导航就利用了这个对象来实现动态跳转。

<router-view> 标签标明了切换路由组件时,路由组件的显示位置。路由导航有两种模式:一种是声明式路由导航,另一种是编程式路由导航。使用 <router-link to="path"> 显示声明路由导航位置就是声明式导航,这种方式适合固定部位导航如顶部的注册登录按钮等,一旦页面要生成的声明式导航过多那么页面就会变的十分卡顿。当链接过多时推荐使用编程式导航来生成导航链接,编程式导航还可以利用事件委托进一步优化页面性能。使用编程式导航时我们只需要给 DOM 元素添加 click 事件,在这个事件触发的函数里我们可以用 $router.push$router.replace 这两个函数完成路由跳转。这两种方式的唯一的区别就是 push 方法生成的链接没有历史浏览记录,无法回退。当需要回退功能时可以使用 replace

# 路由模式

vue-router 有两种路由方式,分别是 hash 模式和 history 模式。一般默认使用 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。在 hash 模式中, URL 路径上会有一个 # 标识符, # 标识符和后面的 URL 片段被称为 hash 。它有以下一些特点:

  • 在第一个 # 后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。
  • 单单改变 #后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
  • 每一次改变 #后的部分,都会在浏览器的访问历史中增加一个记录,使用 "后退" 按钮,就可以回到上一个位置。
  • 可通过 window.location.hash 属性读取 hash 值,并且 window.location.hash 这个属性可读可写。
  • 使用 window.addEventListener ("hashchange", fun) 可以监听 hash 的变化

history 模式是采用 HTML5 标准的 History。当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id ,路径中不会出现 # 。这种模式需要后台的支持,若后台没有做相应处理,则该种模式直接使用 URL 路径访问会无法访问到对应资源。

两种模式的区别:

  • hash 模式相对 history 模式兼容性更好点
  • hash 模式中 # 以后的东西都不会被当作路径发送给后端服务器, history 模式里整个 url 都会被当作请求路径发送给后端服务器,这可能导致刷新页面时,如果没有专门配置 404 页面会导致请求了没有的路径时页面空白
    • history 模式需要后端服务器的支持

# 缓存路由组件

我们都知道当切换路由时原本的路由会被销毁,有时候我们不希望切换路由时原组件被销毁。这时就可以使用路由缓存技术。我们需要在放置 <router-view> 的组件里使用 <keep-alive> 包裹,这样所有在该视图里展示的路由组件都会被缓存。若我们不想所有路由组件被缓存我们可以使用 <keep-alive include="组件名"> 来指定缓存的路由组件,需要缓存多个时可以使用数组的形式 <keep-alive :include="['组件名1','组件名2']"> 。让不展示的路由组件保持挂载,不被销毁

# 两个路由组件独有的生命周期钩子

  • activeated:路由组件被激活(展示)时触发
  • deactivated:路由组件失活(隐藏)时触发

当路由组件被 keep-live 但又不被展示时,我们可以使用这两个钩子来做一些事情。例如停用定时器等等

# 路由守卫

路由守卫可以分为三大类:全局路由守卫、独享路由守卫和组件路由守卫。路由守卫使用的场景通常是需要鉴权的时候,例如有些页面需要登录才能查看,有些页面只能从规定的页面去跳转。

全局路由守卫和独享路由守卫的概念是类似的,只不过全局路由守卫是作用于全局,任何一个组件跳转都要通过全局路由守卫。 beforeEachafterEach 就是提供给我们的两个用于操作组件路由匹配动作前后的函数,其中在所有的守卫中仅 afterEach 没有 next 参数,其它守卫都有 to、from、next 这三个参数。** 这两个函数我理解为类似于 beforeMontedmounted 这两个生命周期钩子,它们分别在路由规则匹配前后工作。** 而独享路由守卫仅有一个匹配前的函数 beforeEnter 供我们使用。

组件路由守卫有三个函数 beforeRouterEnterbeforeRouteUpdatebeforeRouteLeave组件路由守卫都是在组件通过路由规则匹配才能生效的,若不是通过路由规则跳转的则守卫不会被执行。

  • beforeRouterEnter 在渲染该组件的对应路由被 confirm 前调用,并且不能获取组件实例 this 因为当守卫执行前,组件实例还没被创建。

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

  • beforeRouteLeave 导航离开该组件的对应路由时调用,这里的导航离开指的是不显示该组件要去往其它组件时的场景, 可以访问组件实例 this

更新于