vue-router也了解下?

897 阅读8分钟

vue router

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

使用vue-router

安装模块

npm install vue-router

示例

import Vue from 'vue'
import VueRouter from "vue-router"

Vue.use(VueRouter)

import 'Home' form './view/Home'
import 'Channel' form './view/Channel'

// 创建路由实例对象
let router = new VueRouter({
    routers:[{
        path:'/',
        name:'Home',
        alias:'/index', // 别名
        component:Home
    },{
        path: '/(coming_soon|in_theaters|top250)',// 合法的正则都可以;
        component: Channel
    }]
})
export default router

注入vue

import App from './App'
import router from './router'
new Vue({
    el:'#app', // 渲染的挂载点;
    router,    // 路由配置;
    template:'<App />' //使用组件;
    component:{
        App //注入组件
    }
})

this.$router router实例对象,每个组件都可以拿到;vue实例注入的router
this.$route 当前激活的路由信息对象,每个组件实例都会有

告知路由渲染位置: App组件

<router-view></router-view>

hash或者history模式路由

默认hash模式

hash

使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载。 mode:'history'

history

需要支持H5的history api
这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 oursite.com/user/id 就会返回404。
所以呢,在服务端增加一个覆盖所有情况的候选资源:如果URL匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

router-link组件

<router-link></router-link>

跳转地址,不用再切换mode模式时候手动修改进行模式匹配; 前进后退; 点击时默认添加class,可设置; 在router-link组件上设置的class会映射在响应组件的根节点上;

props

to

跳转地址

to="/home"   
:to="home"  
:to="{path:'/home', params: { user: 1 }}" // route.params读取  
:to="{path:'/home', query: { user: 1 }}" // 查询字符串传参,route.query读取 

tag

默认a标签,修改生成标签;

生成a以外的标签不会添加href,默认会添加事件监听来进行url改变;
如果需要查看路径可以在router-link内部再嵌套a标签,此时router-link的to属性会自动渲染到a标签的href属性上;

active-class

默认router-link-active; 路由构造函数选项linkActiveClass: "active"进行全局配置; 单独设置active="pink"优先级高于路由设置;

event

改变默认事件click 事件名

exac

布尔值(出现即可,可省略),路径精确匹配自动触发点击状态,默认是贪婪匹配

append

布尔值(出现即可,可省略),在当前路径后添加此路径

exact-active-class:2.5.0+

默认值: "router-link-exact-active" 路由构造函数选项 linkExactActiveClass 进行全局配置 单独设置router-link-exact-active="pink"优先级高于路由设置

重定向

let router = new VueRouter({
    routers:[{
        path:'*',
        // redirect:'/'
        // redirect:{ path: '/index' },
        // redirect:{ name: 'Home' },
        redirect: (to) => {  //动态设置重定向的目标
            // to:目标路由对象
            // return '/home' //返回跳转路径;
            // 根据不同的path、hash...可以做不同的重定向目标;
            if(to.path === '/about'){
                return 'home';
            }else if(to.path === '/work'){
                return {path:'/home'}
            }else{
                return {name:'Home'}
            }
        }
    }]
})

路由嵌套

let router = new VueRouter({
    routers:[{
        path:'/about'
        alias:'/index',
        component:about,
        children: [{
            path:'', // 默认子路由,设置了默认子路由父路由就不要设置name属性了,否则vue会发出警告,name设置在默认子路由即可;,
            name:'About',
            component:'work'
        },{
            path:'study', // 不用加/,加了就是根路径了
            name:'study',
            component: study
        }]
    }]
})

渲染的位置也是在父级组件里,只需添加<router-view></router-view>
在渲染子路由的时候父组件也会被渲染;
此时渲染路径是/about/study;
如果想要'/study'可以这样处理:
在router-link中to属性使用绑定对象表示:to={name:'Study'};
子路由的path中加上/,形成'/study'; 此时是组件嵌套,路由不嵌套 在渲染时候还是同样的渲染,只是路径上就没有了父级路由;

命名视图

有名字的router-view

<router-view></router-view> // 渲染默认路由
<router-view name="slider"></router-view> // 命名视图渲染
let router = new VueRouter({
    routers:[
        {
            path:'/document',
            alias:'docu',
            name:'Document',
            components:{
            default: document,
            slider: slider
            }
        }
    ]
})

滚动行为

自定义路由切换时页面如何滚动。 这个功能只在支持 history.pushState 的浏览器中可用。

let router = new VueRouter({
    routes: [...],
    scrollBehavior(to, from, savePosition) {
        // 在点击浏览器的前进、后退、切换导航时候触发
        // to:目标路由对象 去哪里
        // from:离开的路由对象 哪里来
        // savePosition:记录滚动条的坐标 只有在点击前进后退的时候记录值
        if (to.hash) { // 有hash使用hash
            return {
                selector:to.hash
            }
        } eles { // 没有hash,检测是否有保存的滚动条坐标;
            if(saverPosition){
                return saverPosition;
            }else{
                return {x:0,y:0};
            }
        }
    }
})

动态路径

匹配到的所有理由,都映射的同一个组件,根据不用的params进行不同的渲染;

let router = new VueRouter({
    routers:[{
        path:'/user/:userId?',  // 正则userId? 表示userId可有1次也可以没有;
        alias:'/user',
        name:'User',
        component:user,
    }]
})

通过this.$route.params.userId读取。
路径改变了,页面信息需要重新渲染怎么办?

new Vue({
    created(){
        // 渲染组件只会调用一次此声明周期函数;
        // 复用这个组件,此声明周期函数不会再次调用;
        // 地址一旦发生变化,$route对象就会重新生成;
        // 所以可以通过监听$route对象来判断路由是否改变;
        // 再根据$route对象来重新渲染页面信息;
        // 导航守卫也可以下面有介绍
    },
    watch:{
        $route(){
            console.log(this.$route);
        }
    }
})

过渡动效

提供了transition的封装组件,添加过渡动画 添加删除css类名

<transition name=”go” mode=”out-in”>
    <router-view></router-view>
</transition>

name:过渡动画前缀;默认是v;
mode:过渡模式:默认同时进行;
in-out:进入的先过渡;
out-in:离开的先过渡;

路由元信息

在路由配置中meta可以配置一些数据,用在路由信息对象中访问meta中数据:$route.meta;

let router = new VueRouter({
    routers:[{
        path:’/’,
        component:home,
        meta:{
            info:'来自index的元信息’
        }
    }]
})

编程式导航

借助 router 的实例方法,通过编写代码来实现

router.push()

声明式 编程式
<router-link :to="..."> router.push(...)

router.push()会向 history 添加新记录,该方法的参数可以是一个字符串路径,或者一个描述地址的对象。
如果提供了 path,params 会被忽略,需要提供路由的 name 或手写完整的带有参数的 path:

const userId = 123
router.push({ name: 'user', params: { userId }})  // -> /user/123
router.push({ path: `/user/${userId}` })          // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

router.replace()

声明式 编程式
<router-link :to="..." replace> router.replace(...)

router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是替换掉当前的 history 记录


router.go(n)  // 在history记录中向前或者后退多少步,正数先前,负数后退
router.back()  // 后退
router.forward()  // 前进

router.push、router.replace 和 router.go 跟 window.history.pushState、 window.history.replaceState 和 window.history.go好像, 实际上它们确实是效仿 window.history API 的。

导航守卫

导航发生变化时,导航守卫用来拦截导航,让它完成跳转或取消

执行导航守卫位置

router实例全局
单路由
组件中

导航守卫

router实例全局

beforeEach、beforeResolve、afterEach
在 2.5.0+ 可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
  // ...
})
router.afterEach((to, from) => {
  // ...
})

单路由

beforeEnter

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

组件内的钩子

beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave;

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    // 此时next可以传入一个函数,接受一个参数,此参数就是组件的实例;
    
    next( (vm)=>{ vm.age='23' } )
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

钩子函数接收的参数

to: 要进入导航的路由对象 到哪里去
from:要离开导航的路由对象 从哪里来
next:用来决定跳转或取消导航
next('/login') 跳转到/login
next() 正常跳转

完整的导航解析流程

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

路由对象属性

表示当前激活的路由的状态信息,每次成功的导航后都会产生一个新的对象。

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 一个数组,包含当前路由的所有嵌套路径片段的路由记录。路由记录就是 routes 配置数组中的对象副本(还有在 children 数组)。

const router = new VueRouter({
  routes: [
    // 下面的对象就是 route record
    { path: '/foo', component: Foo,
      children: [
        // 这也是个 route record
        { path: 'bar', component: Bar }
      ]
    }
  ]
})

当 URL 为 /foo/bar,$route.matched 将会是一个包含从上到下的所有对象(副本)。

route.name
当前路由的名称,如果有的话。(查看 命名路由)

更多API

API参考