vue-router

Posted mengxiangji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue-router相关的知识,希望对你有一定的参考价值。

简介

vue-router和vue.js是深度集成的,适用于单页面应用,传统的路由是用一些产链接来实现页面切换和跳转。而vue-router在单页面应用中,则是组件之间的切换,其本质就是:建立并管理url和对应组件之间的映射关系。

动态路由匹配

定义路由

const router =  new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
    },
    {
      path: '/vue1',
      name: 'vue1',
      component: vue1
    }
  ]
})

页面

<template>
  <div>
    <router-link :to="{name:'vue1',params:{data:111}}">去vue1</router-link>
  </div>
</template>

点击去vue1跳转到http://localhost:8080/#/vue1

组件支持用户在具有路由功能能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。

比起写死的 会好一些,理由如下:
  • 无论是 html5 history 模式还是 hash 模式,它的表现行为一致,所以,当你要切换路由模式,或者在 IE9 降级使用 hash 模式,无须作任何变动。
  • HTML5 history 模式下,router-link 会守卫点击事件,让浏览器不再重新加载页面。
  • 当你在 HTML5 history 模式下使用 base 选项之后,所有的 to 属性都不需要写 (基路径) 了。

跳转的页面接收路由参数

<template>
    <div>
        <button>{{$route.params.data}}</button>
    </div>
</template>

$route.params.data会输出111

响应路由参数的变化

当使用路由参数时,例如从helloWorld/1导航到helloWorld/2,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁在创建,复用则显得更加高效,不过,这也意味着组建的生命周期钩子不会再被调用。

父组件
<template>
  <div class="book">
    <router-link :to="{ name:'vue1',params: { id: 1}}">跳转</router-link>
  </div>
</template>


子组件
<template>
  <div class="book-details">
    <router-link :to="{ name:'vue1',params: { id: 2}}">自己跳自己</router-link>
  </div>
</template>
<script>
export default {
    watch:{
        '$route'(to){
            console.log(to,'监听路由')
        }
    },
}
</script>

技术图片

还有一种方法

<template>
  <div class="book-details">
    <router-link :to="{ name:'vue1',params: { id: 2}}">自己跳自己</router-link>
  </div>
</template>
<script>
export default {
    beforeRouteUpdate(to, from, next){
        console.log(to, from, next,'导航守卫')
        next()
    },
    watch:{
        '$route'(to){
            console.log(to,'监听路由')
        }
    },
}
</script>

使用路由守卫beforeRouteUpdate,这里需要注意一定要加next()

捕获所有路由或404 Not found 路由
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
    },
    {
      path:'*',
      name:'vue2',
      component:vue2
    }
  ]
})

当使用通配符时,必须确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由path:‘*‘通常用于客户端404错误。当我们随便输入一个urlhttp://localhost:8080/#/65446,这时候就会匹配到404页面

高级匹配模式

vue-router使用path-to-regexp作为路径匹配引擎,所以很多高级的匹配模式,例如:可选的动态路径参数,匹配0个或多个,甚至是自定义正则匹配

举个例子

<template>
  <div>
    <router-link :to="{ name:'vue1',params:{data:true}}">跳转</router-link>
  </div>
</template>


   {
      path: '/vue1/:data(\\\\d+)',
      name: 'vue1',
      component: vue1
    },

点击跳转vueRouter会提示[vue-router] missing param for named route "vue1": Expected "data" to match "\\d+", but received "true"

匹配优先级

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高

<template>
  <div>
    <router-link :to="{ name:'vue1'}">跳转</router-link>
  </div>
</template>

// 路由
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
    },
    {
      path:'/vue*',
      name:'vue2',
      component:vue2
    },
    {
      path: '/vue*',
      name: 'vue1',
      component: vue1
    },
    
  ]
})

当面代码中,点击跳转会跳转的vue2这个组件,vue2写在vue1前面,所有vue2的优先级比vue1

嵌套路由

Vue会自带一个最顶层的出口,渲染最高级路由匹配到的组件。同样的,一个被渲染的组件同时可以包含自己的嵌套

组件

<template>
  <div>
    <router-link :to="{ name:'vue1'}">跳转</router-link>
    <router-view></router-view>
  </div>
</template>

路由

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      children:[
        {
          path:'/vue1',
          name:'vue1',
          component:vue1
        }
      ]
    },
  ]
})

注意如果要显示子组件的内容需要<router-view></router-view>接收

当我们访问http://localhost:8080/#/的时候<router-view></router-view>里面是没有内容的

解决办法

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      children:[
        {
          path:'',
          component:vue2
        },
        {
          path:'/vue1',
          name:'vue1',
          component:vue1
        }
      ]
    },
  ]
})

配置一个空的path,这时候访问http://localhost:8080/#/,就会显示vue2组件中的内容

编程式的导航

除了使用创建a标签来定义导航连接,我们还可以借助router的实例方法,通过编写代码来实现。

注意:在vue实例的内部,你可以通过$router访问路由实例。因此你可以调用this.$router.push()。想要导航到不同的URL,则使用router.push方法。这个方法会向history栈添加一个新的记录,所以当用户点击浏览器后退按钮时,则回到之前的URL。

  • 声明式 : <router-link :to="">
  • 编程式 : router.push()
<template>
  <div class="book">
    <router-link :to="{ name:'vue1',params: { id: 1}}">跳转</router-link>
  </div>
</template>

<script>
  export default {
    methods:{
      jump(){
        // 字符串
        this.$router.push('vue1')
        // 对象
        this.$router.push({path:'vue1'})
        // 命名的路由
        this.$router.push({name:'vue1',params:{userId:'123'}})
        // 带查询参数
        this.$router.push({path:'vue1',query:{userId:'123'}}) 
      }
    }
  }
</script>

注意:如果提供了path,params会被忽略。

this.$router.push({name:'vue1',params:{userId:'123'}}) => userId:123
  
this.$router.push({path:'vue1',params:{userId:'123'}}) 不生效

// 正确写法
this.$router.push({path:'vue1',query:{userId:'123'}})
子组件接收也需要使用 $route.query
router.go()

这个方法的参数是一个证书,意思实在history记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。

路由

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/vue1aa',
      name: 'vue1',
      component: vue1
    },
  ]
})

用法

<router-link :to="{ name: 'vue1'}">跳转</router-link>
或者
this.$router.push({name:'vue1'})
嵌套命名视图
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      children:[
        {
          path: 'vue1',
          name: 'vue1',
          components: {
            default: vue3,
            animal: vue1
          }
        },
        {
          path: 'vue2',
          name: 'vue2',
          component: vue2
        }
      ]
    }
  ]
})

当跳转到http://localhost:8080/#/vue2只会显示一个vue2组件,当跳转到http://localhost:8080/#/vue1会显示vue1,vu3两个组件

重定向和别名

 {
      path: '/vue1',
      name: 'vue1',
      component: vue1,
      redirect:'/vue1/vue2',
      children:[
        {
          path: 'vue2',
          name: 'vue2',
          component: vue2
        }
      ]
    }

当我们访问http://localhost:8080/#/vue1会重定向到http://localhost:8080/#/vue1/vue2

重定向的路由也可以是一个命名路由

   {
      path: '/vue1',
      name: 'vue1',
      component: vue1,
      redirect:{name:'vue2'},
      children:[
        {
          path: 'vue2',
          name: 'vue2',
          component: vue2
        }
      ]
    }

甚至是一个方法返回重定向目标

{ 
  path: '/Fruits', 
  redirect: to => {
  // 方法接收 目标路由 作为参数
  // return 重定向的 字符串路径/路径对象
  }
}
别名
{
      path: '/vue1',
      name: 'vue1',
      component: vue1,
      alias: '/haha'
    }

当我们访问的http://localhost:8080/#/haha实际访问的是http://localhost:8080/#/vue1

路由组件传参

组件

<template>
  <div>
    <router-link :to="{ name: 'vue1',params:{id:111222}}">跳转</router-link>
  </div>
</template>

<template>
  <div>
      {{id}} 
  </div>
</template>
<script>
export default {
    props:['id'],
}

路由

 {
      path: '/vue1/:id',
      name: 'vue1',
      component: vue1,
      props:true
    }
布尔模式

在路由配置中设置 props: true 时默认将 $route.params 数据传给组件,组件需要通过自身的 props 属性取出 params 中的属性

对象模式

如果 props 是一个对象,其下所有属性均会被传入组件。需要注意的是当 props 必须是是静态的
路由

 {
      path: '/vue1/:id',
      name: 'vue1',
      component: vue1,
      props:{
        name:'hah',
        age:11
      }
    }
<template>
  <div>
    <router-link :to="{ name: 'vue1'}">跳转</router-link>
  </div>
</template>


<template>
  <div>
      {{name}} {{age}}
  </div>
</template>
<script>
export default {
    props:['name','age'],
}
</script>
函数模式
    {
      path: '/vue1',
      name: 'vue1',
      component: vue1,
      props:()=>({name:'小明'})
    }
<template>
  <div>
      {{name}} 
  </div>
</template>
<script>
export default {
    props:['name'],
}
</script>

HTML5 History 模式

vue-fouter默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面

路由

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      
    },
    {
      path: '/vue1',
      name: 'vue1',
      component: vue1,
      props:()=>({name:'小明'})
    }
  ]
})

来看一下用之前和用之后的地址

// hash
http://localhost:8080/#/

// history
http://localhost:8080/

以上是关于vue-router的主要内容,如果未能解决你的问题,请参考以下文章

百行代码带你入门 vue-router!

typescript vue-router代码分裂

Vue-Router

vue2.0有哪些变化

Vue.js 生态之vue-router

Vue.js 生态之Vue-router 基础三