vue-router

vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。专门用于单页面Web应用实现局部页面更新的插件库。

主要功能:

  • 嵌套路由映射
  • 动态路由选择
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 展示由 Vue.js 的过渡系统提供的过渡效果
  • 细致的导航控制
  • 自动激活 CSS 类的链接
  • HTML5 history 模式或 hash 模式
  • 可定制的滚动行为
  • URL 的正确编码

安装和使用vue-router

步骤一:安装vue-router

  • npm install vue-router –save

步骤二:在模块化项目中使用它

  • 导入路由对象,并调用Vue.use(VueRouter)
  • 创建路由实例,并传入路由映射配置
  • 在Vue实例中挂载创建的路由实例

具体使用

  1. 在src目录下创建router文件夹以及index.js(用于配置路由的相关信息)

    index.js:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../components/About'
    import Home from '../components/Home'

    //创建并暴露一个路由器
    export default new VueRouter({
    routes:[
    {
    path:'/',
    //进行重定向到首页
    redirect: '/home'
    },
    {
    path:'/about',
    component:About
    },
    {
    path:'/home',
    component:Home
    }
    ],
    //设置改变路径的模式 hash/history
    mode: 'history'
    })

    懒加载写法(用到哪个组件就引入哪个组件):

    1
    2
    3
    const Home = () => import(../components/Home)
    const About = () => import(../components/About)
    //其余不变
  2. 在main.js中引入路由

    main.js:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入路由器,自动会导入index.js
    import router from './router'

    //关闭Vue的生产提示
    Vue.config.productionTip = false
    //应用vue-router插件
    Vue.use(VueRouter)

    //创建vm
    new Vue({
    el:'#app',
    render: h => h(App),
    router:router
    })
  3. 在App.vue中使用路由

    App.vue:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <template>
    <div>
    <div class="list-group">
    <!-- 原始html中我们使用a标签实现页面的跳转 -->
    <!-- <a class="list-group-item active" href="./about.html">About</a> -->
    <!-- <a class="list-group-item" href="./home.html">Home</a> -->

    <!-- Vue中借助router-link标签实现路由的切换并且会被渲染成a标签-->
    <router-link to="/about">About</router-link>
    <router-link to="/home">Home</router-link>
    <!-- 指定组件的呈现位置 -->
    <router-view></router-view>
    </div>
    </div>
    </template>
    <script>
    export default {
    name:'App',
    }
    </script>

    router-link标签属性

  • tag=”button”:标签样式
  • replace:开始replace模式:路由标签中加一个replace即可。(浏览器历史记录有两种方式:push和replace;并且默认是push方式;)
  • active-class:设置对应路由匹配成功时的类名,不然默认会使用router-link-active类名(也可以在路由配置中加linkActiveClass配置效果一样)

编程式路由

  • 简写版:this.$router.push/replace('/home')

  • 详细版:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!-- 绑定事件 -->
    <button @click="pushShow(m)">push查看</button>
    <button @click="replaceShow(m)">replace查看</button>

    methods: {
    pushShow(m){
    this.$router.push({
    path:'/home',
    query:{
    id:m.id,
    title:m.title
    }
    })
    },
    replaceShow(m){
    this.$router.replace({
    path:'/home',
    query:{
    id:m.id,
    title:m.title
    }
    })
    }
    },

嵌套路由

操作与一级路由一致,只不过只是将需要嵌入的组件写在路由组件里面

编写路由规则,注意子路由不加 ”/“

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
}
]
}
]
})

在路由组件中写路由标签(注意需要带着父路由的路径)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h2>Home组件内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>

路由params参数

  1. 方式一:

    1
    2
    3
    4
    5
    6
    <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>
    //vue配置
    {
    path:'detail/:id/:title',
    component:Detail,
    }
  2. 方式二(注意这里就不能写path了只能用name指定路由):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- 跳转路由并携带params参数,to的对象写法 -->
    <router-link :to="{
    name:'xiangqing',
    params:{
    id:m.id,
    title:m.title
    }
    }">
    {{m.title}}
    </router-link>

    获得路径参数:this.$route.params.参数

路由query参数

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 方式1: -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>
<!-- 方式2:跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>

获取query参数:

  • <li>消息编号:{{$route.query.id}}</li>
  • <li>消息标题:{{$route.query.title}}</li>

路由props属性

路由配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
name:'xiangqing',
path:'detail',
component:Detail,

//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.query.id,
title:$route.query.title,
a:1,
b:'hello'
}
}
}

组件接收:

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<ul>
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['id','title'],
}
</script>

路由守卫

  • 全局路由守卫

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //创建并暴露一个路由器
    const router = new VueRouter({
    routes:[
    {
    name:'xinwen',
    path:'news',
    component:News,
    meta:{isAuth:true,title:'新闻'}
    }
    ]
    })

    //全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
    router.beforeEach((to,from,next)=>{
    console.log('前置路由守卫',to,from)
    if(to.meta.isAuth){ //判断是否需要鉴权
    if(localStorage.getItem('school')==='cy'){
    next()
    }else{
    alert('学校名不对,无权限查看!')
    }
    }else{
    next()
    }
    })

    //全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
    router.afterEach((to,from)=>{
    console.log('后置路由守卫',to,from)
    document.title = to.meta.title || '系统'
    })

    export default router
  • 独享路由守卫(只有前置没有后置)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    {
    name:'xinwen',
    path:'news',
    component:News,
    meta:{isAuth:true,title:'新闻'},
    beforeEnter: (to, from, next) => {
    console.log('独享路由守卫',to,from)
    if(to.meta.isAuth){ //判断是否需要鉴权
    if(localStorage.getItem('school')==='cy'){
    next()
    }else{
    alert('学校名不对,无权限查看!')
    }
    }else{
    next()
    }
    }
    }
  • 组件内路由守卫

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //通过路由规则,进入该组件时被调用
    beforeRouteEnter (to, from, next) {
    console.log('About--beforeRouteEnter',to,from)
    if(to.meta.isAuth){ //判断是否需要鉴权
    if(localStorage.getItem('school')==='atguigu'){
    next()
    }else{
    alert('学校名不对,无权限查看!')
    }
    }else{
    next()
    }
    },

    //通过路由规则,离开该组件时被调用
    beforeRouteLeave (to, from, next) {
    console.log('About--beforeRouteLeave',to,from)
    next()
    }

缓存路由组件

keep-alive是 Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

1
2
3
4
5
6
7
<!-- 缓存多个路由组件 include中只能写组件名-->
<!-- <keep-alive :include="['News','Message']"> -->

<!-- 缓存一个路由组件 -->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>

有关路由的生命周期钩子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 当该路由组件被激活时调用-->
activated() {
console.log('News组件被激活了')
this.timer = setInterval(() => {
console.log('@')
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
}
<!-- 当该路由组件失活时调用-->
deactivated() {
console.log('News组件失活了')
clearInterval(this.timer)
},