Vue全家桶之一-----Vue-Router

1,451 阅读10分钟
本Vue-Router是根据jspang.com学习笔记所来

第一节、认识Vue-Router

vue-router指的是在vue中的路由管理系统,也就是SPA(单页应用,只有一个index.html页面,所有内容都是index.html里面的组件)

首先需要使用npm i vue-router -S安装一下vue-router ,如果使用了vue-cli,在里面安装过了,这里就忽略

使用vue-cli搭建起来的vue项目, src/router/index.js 这个文件就是路由的核心文件

import Vue from 'vue'   //引入Vue
import Router from 'vue-router'  //引入vue-router
import Hello from '@/components/Hello'  //引入根目录下的Hello.vue组件

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

export default new Router({
  routes: [              //配置路由,这里是个数组
    {                    //每一个链接都是一个对象
      path: '/',         //链接路径
      name: 'Hello',     //路由名称
      component: Hello   //对应的组件模板
    }
  ]
})

接下来新建一个 Hi组件 增加一个Hi路由

  1. src/components 下新建一个 Hi.vue 
  2. Hi.vue 中写入vue组件内容,包括 

 <template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'hi',
  data () {
    return {
      msg: 'Hi, I am JSPang'
    }
  }
}
</script>


<style scoped>

</style>

然后我们就需要配置路由

  1. 打开 src/router/index.js 引入组件import Hi from '@/components/Hi'
  2. 增加路由配置,在router/index.js文件的routes数组中,新增加一个对象

    import Vue from 'vue'   //引入Vue
    import Router from 'vue-router'  //引入vue-router
    import Hello from '@/components/Hello'  //引入根目录下的Hello.vue组件
    import Hi from '@/components/Hi' 
    
    Vue.use(Router)  //Vue全局使用Router
    
    export default new Router({
      routes: [              //配置路由,这里是个数组
        {                    //每一个链接都是一个对象
          path: '/',         //链接路径
          name: 'Hello',     //路由名称,
          component: Hello   //对应的组件模板
        },{
          path:'/hi',
          name:'Hi',
          component:Hi
        }
      ]
    })

至此,就可以通过 http://locolhost:8080/#/hi 访问Hi组件了

最后,我们还需要让他通过类似于<a href=""></a>一样进行跳转

  1. 这里我们先回到 src/App.vue
  2. 然后写一个 <router-link to="">[描述]</router-link>

to    指的是跳转的组件在路由中定义的path
[描述]    指的是显示的文字,与a标签类似

<p>导航 :
   <router-link to="/">首页</router-link>
   <router-link to="/hi">Hi页面</router-link>
</p>

第二节、Vue-Router配置子路由

我们是想通过http://localhost:8080/#/hi/hi1http://localhost:8080/#/hi/hi2 在 hi组件中嵌套子组件

首先改写一下 App.vue 里的<template></template> 的内容

<p>导航 :
      <router-link to="/">首页</router-link> | 
      <router-link to="/hi">Hi页面</router-link> |
      <router-link to="/hi/hi1">-Hi页面1</router-link> |
      <router-link to="/hi/hi2">-Hi页面2</router-link>
</p>

然后改写 components/Hi.vue 页面

跟App.vue一样,也可以写自己的<router-view></router-view>,该 router-view 显示的是 hi组件子路由

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>

    <router-view class="aaa"></router-view>
  </div>
</template>

<script>
export default {
  name: 'hi',
  data () {
    return {
      msg: 'Hi, I am JSPang'
    }
  }
}
</script>
<style scoped>

</style>

接下来我们在components下面新建两个组件 hi1.vuehi2.vue

h1.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
<script>
export default {
  name: 'hi',
  data () {
    return {
      msg: 'Hi, I am Hi1!'
    }
  }
}
</script>
<style scoped>

</style>

hi2.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
<script>
export default {
  name: 'hi',
  data () {
    return {
      msg: 'Hi, I am Hi2'
    }
  }
}
</script>
<style scoped>
</style>

最后我们修改 src/router/index.js 来修改路由配置

子路由的写法是在原有的路由配置下加入children字段

import Vue from 'vue'   
import Router from 'vue-router'  
import Hello from '@/components/Hello'  
import Hi from '@/components/Hi' 
import Hi1 from '@/components/Hi1' 
import Hi2 from '@/components/Hi2' 

Vue.use(Router) 

export default new Router({
  routes: [             
    {                    
      path: '/',        
      name: 'Hello',     
      component: Hello   
    },{
      path:'/hi',
      component:Hi,
      children:[
        {path:'/',component:Hi},
        {path:'hi1',component:Hi1},
        {path:'hi2',component:Hi2},
      ]
    }
  ]
})

第三节、Vue-Router的路由传参

路由传参有两种方法 
  1. name传参
  2. to传参

首先第一种 name 传参

  1. 在路由文件src/router/index.js里配置name属性

routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    }
]

  2.模板里(src/App.vue)$route.name的形式接收,比如直接在模板中显示

<p>{{ $route.name}}</p>

第二种用 to 传参

先来看一下to传参的基本语法

<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>

  • name:就是我们在路由配置文件中起的name值
  • params:就是我们要传的参数,它也是对象形势,在对象里可以传递多个值

接下来改造一下src/App.vue里的<router-link>标签,我们把hi1页面的<router-link>进行修改

跳转到hi1组件,并传参username
 <router-link :to="{name:'hi1',params:{username:'jspang'}}">Hi页面1</router-link>

src/reouter/index.js文件里给hi1配置的路由起个name,就叫hi1

{path:'/hi1',name:'hi1',component:Hi1}

最后在模板里(src/components/Hi1.vue)$route.params.username进行接收

{{$route.params.username}}

第四节、单页面多路由区域操作

可以用来实现在同一个页面上有多个区域且互不影响

首先,在App.vue中写入如下代码

指的是在App.vue中显示三个组件,其中有一个未命名,为默认组件,其余两个为命名组件

<router-view ></router-view>
<router-view name="left" style="float:left;width:50%;background-color:#ccc;height:300px;"></router-view>
<router-view name="right" style="float:right;width:50%;background-color:#c0c;height:300px;"></router-view>

然后我们在src/components下新建两个组件 Hi1.vueHi2.vue

Hi1.vue

<template>    
    <h2>{{msg}}</h2>
</template>

<script>
export default {
    name:'Hi1',
    data(){
        return{
            msg:' I\'m  Hi1'
        }
    }}
</script>

<style scoped>

</style>

Hi2.vue

<template>
    <h2>{{msg}}</h2>
</template>

<script>
export default {
    name:'Hi2',
    data(){
        return{
            msg:' I\'m  Hi2'
        }
    }}
</script>

<style scoped>

</style>

最后我们再配置路由文件 src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import Hi1 from '@/components/Hi1'       //引入Hi1.vue
import Hi2 from '@/components/Hi2'       //引入Hi2.vue

Vue.use(Router)
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      components: {                   //如果有多个router-view,component改为components
        default : Hello,              //未命名组件(默认组件) 指向 Hello
        left: Hi1,                    //left 组件指向 Hi1
        right: Hi2                    //right 组件指向 Hi2
      }
    }
  ]
})


如果我们想把name为left的router-viewname为right的router-view 调换位置,可以改变路由配置中的leftright的指向

当我们输入http://localhost:8080/#/jspang的时候,left组件right组件调换位置

routes: [
    {
      path: '/',
      name: 'Hello',
      components: {
        default : Hello,
        left: Hi1,
        right: Hi2
      }
    },
    {
      path: '/jspang',
      name: 'Hello',
      components: {
        default : Hello,
        left: Hi2,
        right: Hi1
      }
    }
  ]


第五节、Vue-Router利用url传参

首先,我们先配置路由文件src/router/index.js  

这里的:newsId:newsTitle指的是组件中要传的参数

routes: [
    {
      path: '/',
      name: 'Hello',
      component:Hello
    },{
      path:'/params/:newsId/:newsTitle',
      component:Params
    }
  ]

然后在路由文件中引入组件(尽管我们还没有)

import Params from '@/components/params'

现在我们开始新建组件

src/components下新建一个params.vue组件
这里通过 $route.params.newsId $route.params.newsTitle 来接收参数

<template>
    <div>
        <h2>{{msg}}</h2>
        <p>{{$route.params.newsId}}---{{$route.params.newsTitle}}</p>
    </div>
</template>

<script>
export default {
    name:'Hi2',
    data(){
        return{
            msg:'params pages'
         }
    }}
</script>

<style scoped>

</style>

接下来我们在App.vue中传参

跳转到params组件并传入newsId198,传入newsTitlejspang website is very good

<router-link to="/params/198/jspang website is very good">params</router-link>

还有一个问题是,这里的newsId可以传入任何东西,当我们在实际开发中,只希望newsId只可以传数字,这时候可以使用正则表达式来限制newsId的参数,在路由配置的时候使用正则表达式

{
    path:'/params/:newsId(\\d+)/:newsTitle',
    component:Params
}

第六节、Vue-Router的重定向-redirect

首先配置路由文件

routes: [
    {
      path: '/',
      name: 'Hello',
      component:Hello
    },{
      path:'/params/:newsId(\\d+)/:newsTitle',
      component:Params
    },{
      path:'/gohome',
      redirect:'/'
    }
  ]

然后在App.vue中添加一个router-link

<router-link to="/gohome">gohome</router-link>

这样点击这个gohome就会重定向到首页 

当我们重定向的时候也想像上一节一样传递参数的情况怎么实现呢

首先配置路由文件

routes: [
    {
      path: '/',
      name: 'Hello',
      component:Hello
    },{
      path:'/params/:newsId(\\d+)/:newsTitle',
      component:Params
    },{
      path:'/gohome',
      redirect:'/'
    },{
      path:'/params/:newsId(\\d+)/:newsTitle',
      redirect:'/params/:newsId(\\d+)/:newsTitle'   //重定向的路径与path一致
    }
  ]

最后在App.vue中做个跳转的功能

<router-link to="/goparams/178/goparams">goparams</router-link>

第七节、路由的过渡动画

首先将需要过渡的<router-view><router-view><transition></transition>包裹起来

<transition></transition>中有两个属性

  1. name 定义动画名称
  2. mode 定义动画过渡模式

现在我们定义了动画名称为fade,他将有下面四个类名需要定义

  1. fade-enter:进入过渡的开始状态,元素被插入时生效,只应用一帧后立刻删除。
  2. fade-enter-active:进入过渡的结束状态,元素被插入时就生效,在过渡过程完成后移除。
  3. fade-leave:离开过渡的开始状态,元素被删除时触发,只应用一帧后立刻删除。
  4. fade-leave-active:离开过渡的结束状态,元素被删除时生效,离开过渡完成后被删除。

mode有两种过渡模式

  1. in-out  先进后出(默认)
  2. out-in  先出后进

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

然后定义我们的css样式

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

这样我们的组件切换的渐入渐出效果就出现了

第八节、mode的设置和404页面的处理

这里的mode不是上一节中的过渡效果的mode

在路由配置文件中,有一个属性mode,mode有两个值可以设置,(看个人喜好)

  1. history 路径后面没有#,比如 http://localhost:8080/
  2. hash 路径后面会跟上#,(默认),比如 http://localhost:8080/#/

export default new Router({
  mode:'history',
  routes: [
    {
      path: '/',
      name: 'Hello',
      component:Hello
    }
 ]
})

当我们在路径后面随便跟上一个错误路径的时候,需要页面反馈给我们信息,这时候就用到404页面了

首先在路由配置文件中routes数组中配置如下

{    path:'*',    component:Error}

然后在路由配置文件中引入Error组件

import Error from '@/components/error'

接下来我们在src/components下新建一个error.vue

<template>
    <div>
        <h2>{{msg}}</h2>
        <h2>页面不存在!</h2>
    </div>
</template>

<script>
export default {
    name:'Hi2',
    data(){
        return{
            msg:' ERROR 404'
         }
    }}
</script>

<style scoped>

</style>

这个时候,当我们在路径后面写上路由配置文件没有配置的路径时,就会进入404页面

第九节、路由中的钩子

路由配置文件中的钩子函数

首先在一个路由配置文件中一个路由下面写下如下

export default new Router({
  mode:'history',
  routes: [
    {
      path: '/',
      name: 'Hello',
      component:Hello
    },{
      path:'/params/:newsId(\\d+)/:newsTitle',
      component:Params,
      beforeEnter:(to,from,next)=>{
        //console.log(to)   //对象  跳转到哪里
        //console.log(from) //对象  从哪里跳转过来
        next();
        // next(true);     //允许跳转
        // next(false);    //禁止跳转
        // next({path:'/'});    //跳转到根目录
      }
    },
    ...
  ]
})

写在模板中的钩子函数

打开之前写好的src/components/params.vue ,修改为如下

<template>
    <div>
        <h2>{{msg}}</h2>
        <p>{{$route.params.newsId}}---{{$route.params.newsTitle}}</p>
    </div>
</template>

<script>
export default {
    name:'Hi2',
    data(){
        return{
            msg:'params pages'
         }
    },
    beforeRouterEnter:(to,from,next) => {
        console.log('准备进入params路由模板')
        next();
    },
    beforeRouterLeave:(to,from,next) => {
        console.log('准备离开params路由模板')
        next();
    }
}
</script>

<style scoped>

</style>

需注意一项,钩子函数中的next()必须写,如果不写路由是跳转不过去的,相当于被拦截了

第十节、Vue-Router的编程式导航

首先在App.vue中模板中写入

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

然后在App.vuescript部分写下

methods:{
    goGo(){
        this.$router.go(1)
    },
    goBack(){
        this.$router.go(-1)
    }
}

这样就实现了一个类似于浏览器前进后退的功能

接下来要实现一个跳转到指定页面

App.vue模板中再新增一个button

<div>
    <button @click="goGo">前进</button>
    <button @click="goBack">后退</button>
    <button @click="goHome">返回首页</button>
</div>

然后在App.vuescript部分再新增一个methods

methods:{
    goGo(){
        this.$router.go(1)
    },
    goBack(){
        this.$router.go(-1)
    },
    goHome(){
        //this.$router.push('/')
        this.$router.push({path:'/'})
    }
}