Published on

Vue-router,在静态切换的世界中翱翔

Authors
  • avatar
    Name
    Hansuku
    Twitter

什么是 router

首先知道,Vue 是适合在 SPA(单页应用)开发中使用的,router 能够做到类似 html5 和 jQuery 中的 pjax(局部刷新,无刷新切换路由)的效果,也是 Web 应用的路由管理系统。

router 快速上手

  • 安装 Vue-router npm install vue-router --save-dev 如果配置过 vue-cli 则不需要主动去安装 Vue-router,在安装 Vue-cli 的时候是可以选择一起安装的。
  • Vue 配置 安装会在源码目录下安装 router 文件夹和 index.js 文件 默认配置:
import Vue from 'vue' //引入Vue
import Router from 'vue-router' //引入Vue-router
import HelloWorld from '@/components/HelloWorld' //引入Components里的HelloWorld.vue

Vue.use(Router) //全局使用路由

export default new Router({
  routes: [
    //路由配置数组
    {
      path: '/', //路径
      name: 'HelloWorld', //路由名称
      component: HelloWorld, //模板组件
    },
  ],
})

尝试在 components 下新建一个 vue 模板,然后在 index.js 里写入

        {
          path:'/Hi',
          name:'Hi',
          component:Hi
        }

在 router 里根据上面的格式写入路由数组就可以添加路由,并且还要在头部 import 引入一下import Hi from '@/components/Hi' 然后看到 src 源码目录下的 App.vue,这里是 VueRouter 的全局页面

    <template>
      <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
      </div>
    </template>

    <script>
    export default {
      name: 'app'
    }
    </script>

    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>

我们打开本地阅览,尝试在 host 后面加上 Hi,发现可以跳到刚刚配置的 Hi.vue 页面,但是只有局部,上面 Vue 默认的图片还是存在,这就是 router 的奇妙之处,在刚刚打开的 App.vue 里,可以看到一句<router-view/>这里就是 Vue 作为引导,把其他路由页面加入到这个页面的组件。设想我们需要做一个 SaaS,就可以在这个页面写导航栏,而剩下的部分则依靠<router-view/>引入切换

  • 说到导航栏,其实 Vue 给我们提供了一个新标签(也可以说是新组件),来制作导航栏 我们在 App.vue 全局页面里写入
<template>
	  <div id="app">
	    <img src="./assets/logo.png">
	    <div>
	      <router-link to="/">首页</router-link>
	      <router-link to="/Hi">Hi</router-link>
	    </div>
	    <router-view/>
	  </div>
</template>

然后在浏览器中看到,已经有了两个导航按钮 我们注意到地址栏,然后点击 Hi,发现已经能够无需刷新网页,就可以切换页面和路由,这就是 router 的强大之处

子路由

在实际构建网站中,我们会遇到二级栏目的情况,例如我们鼠标 hover 到关于上,会显示出关于我们和联系我们,这两个栏目都隶属于关于,所以就有了子路由的配置 假设我们把导航变成

    <div>
      <router-link to="/">首页</router-link>|
      <router-link to="/Hi">Hi页面</router-link>|
      <router-link to="/Hi1">Hi1页面</router-link>|
      <router-link to="/Hi2">Hi2页面</router-link>
    </div>

Hi1 和 Hi2 是 Hi 的子页面,然后我们希望这两个子页在 H 页面的底部,这种情况的话,我们需要在之前 components 下的 Hi.vue 写入

    <template>
      <div>
        <h2>{{ msg }}</h2>
        <router-view/>
      </div>
    </template>

新建 Hi1.vue 和 Hi2.vue,改改 msg 做区别,然后在 index.js 写入路由配置

    {
      path:'/Hi',
      name:'Hi',
      component:Hi,
      children:[
        {path:'/Hi1',component:Hi1},
        {path:'/Hi2',component:Hi2},
      ]
    }

这样就可以让 Hi1 和 Hi2 继承 Hi

参数传递

在 OA 和 SaaS 开发中,我们经常遇到需要在路由中传递参数的情况,而使用 router 时<router-link to="/">首页</router-link>|并不能传递参数,那就可以使用之前 index.js 在配置路由时一直没用过的 name

    {
      path: '/',
      name: 'youNeed',
      component: HelloWorld
    }

假设我们需要在跳转到 HelloWorld 的时候接收到 youNeed 首先在 App.vue 全局页面写一个假装是面包屑的标签 <p>{{ $route.name }}</p> 保存好,然后就在 HelloWorld 页面看到我们定义的 youNeed 然后尝试给有子路由增加 name 参数

    {
      path:'/Hi',
      name:'Hi',
      component:Hi,
      children:[
        {path:'/hi1',name:'here hi1',component:Hi1},
        {path:'/hi2',name:'here hi2',component:Hi2},
      ]
    }

也能在浏览器中看到效果了。 但是这种方法并不常用,实际开发中,我们的传参是动态的,那就需要改造一下<router-link to="/Hi1">Hi1页面</router-link> 改造成

<router-link :to="{ name:'here hi1',params:{username:'Hansuku',id:'666' }}">Hi1页面</router-link>

这里的 name 要和 index.js 路由配置中的 name 一致,params 接数组对象,然后在 Hi1 模板写入

<h2>{{ msg }}-{{ $route.params.username }}-{{ $route.params.id }}</h2>

这样就能接收到参数了。我们可以通过动态传参的方法去更改 username 和 id 的 value.

单页面多路由操作

什么是单页面多路由操作,假设一个页面里我们有几个区域,需要引入几个模块,则需要在这个页面

    <router-view/>
    <router-view name="left"/>
    <router-view name="right"/>

然后我们新建一个 hello1.vue 和 hello2.vue 写好相应的区分,在 index.js 中写入路由配置:

    {
      path: '/',
      name: 'youNeed',
      components: {
        defaule:HelloWorld,
        left:Hello1,
        right:Hello2
      }
    }

deafult 是默认配置,left 和 right 则对应了刚才的<router-view name="left"/>,刷新就能看到效果了

通过 url 传递参数

上面提到的传递参数的方法,都是不会在 url 中体现的,而有的时候我们会喜欢用 url 来辨识文章或者一些操作,那就需要用 url 传参 新建一个 params.vue 的模板

    <template>
	  <h2>{{msg}}</h2>
	</template>
	<script>
	  export default{
	    data(){
	      return{
	        msg:'parmas pages'
	      }
	    }
	  }
	</script>

index.js 引入import Params from '@/components/params 添加路由

    {
      path:'/params/:newsID/:newsTit',
      component:Params
    }

这里的格式是路径+冒号+属性 然后在 App.vue 导航栏加个<router-link to="/params/200/hansuku you">params</router-link> params 后面跟着的其实就是 url 参数了,点击试试就能看到路由中已经带了参数。接收方式有很多种,vue 的方法是

    <p>newsID:{{ $route.params.newsID }}</p>

配置路由时还能做一些验证,比如 newsID 必须是数字

    path:'/params/:newsID(\\d+)/:newsTit',

直接括号里面写正则即可

router 重定向

重定向即两个不同的路由打开的页面是一样的,类似返回首页的效果。 添加路由规则配置

    {
      path:'/goIndex',
      redirect:'/'
    }

在 App.vue 里添加一个导航<router-link to="/goIndex">返回首页</router-link>即可 重定向传参 类似上面的路由传参,添加路由配置

    {
      path:'/goParams/:newsID(\\d+)/:newsTit',
      redirect:'/params/:newsID(\\d+)/:newsTit'
    }

添加导航: <router-link to="/goParams/199/thisIsParams2">params2</router-link> 一样可以传递参数并且跳转。主要,如果是重定向的 path 里写入了参数传递,而跳转的时候没有带参数,跳转后在页面内会什么都不显示

alias 别名

alias 别名的方式也可以实现类似重定向的效果,区别在于上面的 redirect 跳转后 url 内的地址就是重定向的地址,不会有区别,而 alias 别名是一个新的 url 地址,但是页面是一样的

    {
      path:'/Hi1',
      name:'Hi1',
      component:Hi1,
      alias:'/Hansuku'
    }

这个时候,导航<router-link to="/Hi1">Hi1</router-link><router-link to="/Hansuku">Hansuku</router-link>跳转的页面内容是一样的,但是地址是http://localhost:8080/#/Hi1http://localhost:8080/#/Hansuku

路由过渡动画

在路由切换的时候,由于用户体验不到刷新感,我们需要增添一些过渡动画来提升用户体验 在 router-view 标签即页面会切换内容的地方包裹一层 transition

    <transition name="fade" mode="out-in">
      <router-view/>
    </transition>

name 代表渐入渐出式,mode 是出入循序

    out-in 代表先出后入
    in-out 代表先入后出

然后增加 css

    .fade-enter {
	  opacity:0;
	}
	.fade-leave{
	  opacity:1;
	}
	.fade-enter-active{
	  transition:opacity .5s;
	}
	.fade-leave-active{
	  opacity:0;
	  transition:opacity .5s;
	}

这样就有了一个比较基础的切换效果

路由模式

    export default new Router({
	  mode:'history',
	  routes: [
	    {
	      path: '/',    //路径
	      name: 'HelloWorld',    //路由名称
	      component: HelloWorld    //模板组件
	    }
	  ]
	})

这里的 mode 代表路由模式,加上 mode:'history'后,本身我们路由里面会带一个#号,现在就消失了,mode 还有一个模式 mode:'hash'这个模式会带上#号,选择上个人喜好就好。

404 处理

VUE 如果不配置,发生了 404 的情况下用户会比较懵逼的,不知道网页出了什么错,就是不显示 添加配置

    {
      path:'*',
      component:Error
    }

*就是对所有没有的路由展示 Error 页面 引入import Error from '@/components/Error' 然后自由配置一个 404 模板即可

路由中的钩子函数

钩子函数能够监听两个状态,一个是进路由之前,一个是离开路由之前,配置钩子函数可以在 index 中写,也可以在模板中写 index.js 中的钩子函数

    {
      path:'/params/:newsID(\\d+)/:newsTit',
      component:Params,
      beforeEnter:(to,from,next)=>{
        console.log(to),
        console.log(from),
        next(true)
      }
    }

next(true)是相当于一个开关的角色,如果换成了 false 就不会进行跳转,如果不写也会导致不跳转 模板中的钩子函数

    export default{
	    data(){
	      return{
	        msg:'parmas pages'
	      }
	    },
	    beforeRouteEnter:(to,from,next)=>{
	        console.log("进入");
	        next()
	    },
	    beforeRouteLeave:(to,from,next)=>{
	        console.log("离开");
	        next()
	    }
	  }

编程式导航

假设需要一个后退和前进的按钮(类似 chrome 左上角的按钮) html

    <button @click="goBack">后退</button>
    <button @click="goDo">前进</button>

script

    export default {
	  name: 'app',
	  methods:{
	    goBack(){
	      this.$router.go(-1);
	    },
	    goDo(){
	      this.$router.go(1);
	    }
	  }
	}

需要注意的是,在没有历史记录的情况下$router.go 是不起作用的

  • 编程式跳转
    <button @click="goHome">返回首页</button>
goHome(){
      this.$router.push('/');
    }

方法跟$router.go 大同小异,可以 push 任意页面