Vue 路由配置教程


一、基本介绍

当你第一次初始化 Vue 项目并启动会发现首页内容是 Vue 基本介绍,但在查看 App.vue 的源码之后却发现并没有相关的实现代码。

那么问题来了,首页的内容是从何渲染而来?

答案很简单,就是通过路由显示。先让我们看一个简单的例子感受一下,如下图你所看到的是我的首页。

当我点击 Table 按钮时,你会发现标题显示并未发生变化,但页面显示内容已经发生变化。

这就是路由跳转的最基本的案例,下面介绍具体配置步骤。

二、页面注册

1. 页面注册

在实现跳转之前,我们需要先对每个页面进行注册。首先需要将要路由的页面在 router/index.js 文件中进行注册,为每个页面分配不同路由地址。

注意在引入组件时有两种方式,根据自己喜好进行选择,具体配置如下:

import Home from '@/components/home'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      // 通过头部引入进行引用
      component: Home
    }, {
      path: '/table',
      name: 'Table',
      // 直接引入组件
      component: () => import('@/views/table/index')
    }
  ]
})

需要注意的一点是这里添加 mode: 'history' 用于去除默认地址栏中 # ,因为 vue 的路由默认是 hash 模式,在路由跳转时会导致地址无法重置,这里进行去除。

2. 重定向

我们也可以通过 redirect 属性将路由请求重定向到其它页面,如将 / 请求重定向到 /login ,配置代码如下:

routes: [
  {
    path: '/',
    redirect: '/login'
  }, {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/login/index')
  }
]

3. 异常处理

我们同样也可将未定义的路由请求统一重定向到提前设置的 404 页面,代码如下:

routes: [
  {
    // 未定义页面重定向到 404
    path: '*',
    redirect: '/404'
  }, {
    path: '/404',
    name: '404',
    component: () => import('@/views/error/404')
  }
]

三、组件路由

router/index.js 文件中注册完页面,下面就可以实现路由跳转了。实现路由跳转的方式主要分两类:第一种就是直接在标签控件配置路由,第二类就是将路由实现写在方法内。

下面将分别对两种方法进行介绍。

1. 组件跳转

在首页 views/index.vue 页面添加路由跳转实现代码。

这里先说明一下,默认的项目启动页显示的是 App.vue 页面,如需要修改默认启动页则修改项目根目录 mian.js 中配置即可,可以自行模仿原有样例进行修改,这里不作详细介绍。

路由配置示例代码如下:

<template>
  <div id="app">
    <h1>This is Vue Demo</h1>
          
    <router-link to="/">
      <a-button>Home</a-button>
    </router-link>
    <router-link to="/table">
      <a-button>Table</a-button>
    </router-link>

    <!-- 这里一定要加 router-view 标签 !!! -->
    <router-view />

  </div>
</template>

这里的 <router-link> 组件中的 to 属性需要和上一步配置的 path 属性值一致。需要注意的一点这里一定不要漏了 <router-view /> ,否则将无法成功进行路由跳转。

2. 方法跳转

除了直接通过 router-link 组件实现路由跳转也可使用 $router 实现同样的功能,后者相较前者能够配合判断验证用户请求,最常见的场景就是在用户进行登录验证后的页面跳转。

具体代码如下:

methods:{
  ok() {
    if (/* 验证信息 */) {
      // 验证合法进行跳转
      this.$router.push('/home')
    }
  }
}

3. 跨服务跳转

上面的两种路由方式都是基于当前服务实现路由跳转的,但是如果想要实现跨服务跳转上述方式显然是行不通的。如在 A 系统的首页想要跳转到 B 系统的首页因为不在同一个项目中,很显然不能通过配置路由进行跳转,此时就可以通过 window.location.href 实现跨服务跳转的效果。

具体实现如下:

methods:{
  ok() {
    // 跨服务跳转
    window.location.href = '/b/home?id=123'
  }
  receive() {
    // 参数获取
    const url = window.location.href
    console.log(url)
    // 参数为中文时需要解码
    console.log(decodeURI(url))
  }
}

4. 页面刷新

(1) 添加判断

若使用路由跳转则可以通过配置路由出口组件实现页面刷新,在路由父页面的 router-view 标签内添加判断。

<template>
    <div>
        <router-view v-if="isRouterAlive"/>
    </div>
</template>
(2) 刷新方法

在该页面中编写相应的刷新方法。

data() {
    return {
        isRouterAlive: true
    }
},
provide() {
    return {
        reload: this.reload
    }
},
methods: {
    reload() {
        this.isRouterAlive = false
        this.$nextTick(function () {
            this.isRouterAlive = true
    })
    }
}
(3) 调用刷新

在需要刷新的子页面引入 reload ,并通过调用 this.reload() 实现页面刷新。

<script>
    inject: ['reload'],
    methods:{
    refresh(){
        this.reload()
    }
    }
</script>

四、路由传参

在实现不同页面间的跳转时往往需要进行参数的传递,路由传参的方式主要也有两大类,一种是将参数拼接的地址后,类似 Get 请求,另一种则类似 Post 进行隐式传参。

下面同样对两种方式进行分别介绍。

1. 路径无参

此方式类似 Post 请求地址栏将不会拼接显示参数值。

(1) 参数传递

可以通过上面介绍的第一种跳转方式,利用组件进行跳转传参。

<router-link 
    :to="{
        path:'/login', 
        params: { id: '1' }
    }"
/>

也可以通过 $router 实现跳转传参,更常用。

methods:{
    jump() {
        this.$router.push({
            path:'/login',
            params: {
                id: '1'
            }
        })
    }
}
(2) 参数获取

通过 $route.params 获取传递的参数,通过写在路由目标的声明周期中如 mounted 中,在页面加载时即获取参数。

mounted() {
    const _id = this.$route.params.id
    console.log(_id)
}

2. 路径带参

此方式类似 Get 请求将参数拼接的地址后,如 localhost:8080/table?id=1

(1) 参数传递

和之前的一样带参跳转同样提供两种方式。

<router-link 
    :to="{
        path:'/table', 
        query: { id: '1' }
    }"
/>
methods:{
    jump() {
        this.$router.push({
            path:'/table',
            query: {
            id: '1'
            }
        })
    }
}
(2) 页面取值

通过 $route.query 获取传递的参数,

mounted() {
    const _id = this.$route.query.id
    console.log(_id)
}

五、嵌套路由

在上面我们介绍了如何进行路由跳转,但都是从基于跳转新页面。但如果想要实现页面内嵌套跳转呢?

最常见的场景就是我们的侧边菜单跳转了,如下当我们选择左侧不同模块时,右侧的内容区域应该要根据我们的选择展示不同内容,也就是达到如下效果:
数据监控
后勤管理

1. 页面注册

首先还是和上面的类似,我们需要在 router/index.js 文件中对页面进行注册,将需要嵌套的页面注册在其父页面内。

这里我在 /home 路由下嵌套了两个子页面,具体配置如下:

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Login',
      component: () => import('@/views/login/index')
    }, {
      path: '/home',
      name: 'Home',
      component: () => import('@/views/home/index')
      children: [
        {
          path: '/home/monitor',
          component: () => import('@/views/monitor/index')
        }, {
          path: '/home/staff',
          component: () => import('@/views/staff/index')
        }
      ]
    }
  ]
})

export default router

2. 嵌套页面

这里我结合了 Antd 的布局组件更美观的展示内容,当然也可以使用其他框架。

(1) 页面实现

具体代码如下:

<a-layout>
    <a-layout-sider>
        <a-menu theme="dark" mode="inline" :default-selected-keys="['1']">
            <a-menu-item key="1">
                <span @click="routePage('monitor')">数据监控</span>
            </a-menu-item>
            <a-menu-item key="2">
                <span @click="routePage('staff')">员工管理</span>
            </a-menu-item>
        </a-menu>
    </a-layout-sider>

    <a-layout-content>
        <!-- 路由出口,页面展示区域 -->
        <router-view />
    </a-layout-content>
</a-layout>
(2) 事件绑定

为菜单按钮绑定点击事件,当用户点击时进行路由跳转。

methods:{
    routePage(data) {
        switch (data){
            case 'monitor':
                this.$router.push('/home/monitor')
                break
            case 'staff':
                this.$router.push('/home/staff')
                break
        }
    }
}

3. 循环异常

按照上面的配置当你重复点击跳转同一个页面时控制台将会报错,提示 Avoided redundant navigation to current location 表明在进行重复的路由。

因此我们需要对此进行额外处理,在 router/index.js 文件末尾添加以下代码,需要注意这里 Router.prototypeRouter 要和 Vue.use(Router) 中名称一致。

const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

六、登录过滤

通过路由我们不仅可以实现页面跳转,同时也能实现对路由请求判断从而实现登录过滤。

举个简单例子,我的工程一共由两个页面:登录页 /login 和主页 /home。项目启动时默认为登录页,当用户登录之后跳转至首页,如果用户未登录尝试访问首页,此时应该将跳转请求重定向到登录页。

同理,当用户完成登录之后访问登录页我们也应该将该请求重定向到首页,只有在用户选择退出登录之后才能重新访问登录页面。

具体配置步骤如下

1. 配置过滤

首先需要在 router/index.js 文件中进行配置过滤,对于未登录状态的请求重定向至登录页面。

router.beforeEach((to, from, next) => {
  let token = localStorage.getItem('token') == null
  // 1. 是否为登录页
  if(to.path === '/login') {
    // 2. 未登录放行,已登录回首页
    token ? next() : next('/home')
  } else {
    // 3. 未登录转登录页,已登录则放行
    token ? next('/login') : next()
  }
})

2. 设置状态

上面我们只是配置了判断规则,现在我们就要在页面进行相应的逻辑处理。

当用户完成登录之后,我们需要将状态设置 1 放行。

methods:{
  ok() {
    localStorage.setItem('token', '1')
  }
}

3. 关闭状态

同样的当用户选择退出之后,我们就应该将登录状态清空并返回登录页。

methods:{
  quit() {
    // 清楚登录状态并返回首页
    localStorage.removeItem('token')
    this.$router.push('/login')
  }
}

4. 过期时间

在现实的开发需求中,我们往往需要设置登录过期时间,类似于传统 cookies 过期时间。而 localStorage 默认是没有时间属性的,所有需要我们进行自定义。

因为 localStorage 存入的键值对默认都为字符串,这里用到 JSON 格式的对象转化实现存入对象数据。

(Ⅰ) Vue 页面存入数据代码如下:

let items = {
    flag: '123',
    startTime: new Date().getTime()
}
localStorage.setItem('token', JSON.stringify(items))

(Ⅱ) router/index.js 文件判断代码如下:

// 过期时间为一天,时间戳形式
let ExpiresTime = 86400000

router.beforeEach((to, from, next) => {
    let token, isLogin

    // 1. 将存入的字符串转对象
    token = JSON.parse(localStorage.getItem('token'))

    // 2. 状态判断
    isLogin = !(token == null || token.flag == null || token.flag === '')

    // 3. 登录时间超过一天需要重新登录
    if(isLogin){
        let date = new Date().getTime();
        if (date - token.startTime > ExpiresTime) {
            localStorage.removeItem('token')
            isLogin = false
            this.$message.error('登录过期,请重新登录')
        }
    }

    // 4. 是否为登录页
    if(to.path === '/login') {
        // 4.1. 已登录则回首页,未登录放行
        isLogin ? next('/home') : next()
    } else {
        // 5. 已登录则放行,未登录转登录页
        isLogin ? next() : next('/login')
    }
})

文章作者: 烽火戏诸诸诸侯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 烽火戏诸诸诸侯 !
  目录