vue router路由解析

标签: # vue  vue  vue router

一、前言

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

二、安装

1.安装包

npm install vue-router

2.项目引用

在cli4脚手架目录router下index.js中引用

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

三、使用

1.路由命名

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

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})
const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

(2) 要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

这跟代码调用 router.push() 是一回事:

router.push({ name: 'user', params: { userId: 123 }})

这两种方式都会把路由导航到 /user/123 路径。

2.重定向与别名

(1)重定向
通过 routes 配置来完成,下面例子是从 /a 重定向到 /b

 {
      path: '/A',
      name: 'A',
      component: A,
      redirect: '/B'
    }
    
或者
    
redirect: { name: 'B' }    

(2)别名
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。

3.History 模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

使用

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

当你使用 history 模式时,URL 就像正常的 url,例如 http://xxx.com/user/id

不过这种模式要玩好,还需要后台配置支持。如果后台没有正确的配置,当用户在浏览器直接访问就会返回404错误。所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

Nginx相关配置

location / {
           root D:/Web/Project/testdemo/dist;   //项目路径
           try_files $uri $uri/ /index.html last; //跳转至index.html
           index  index.html index.htm;
    }

为了避免 404 错误页面,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})
4.命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})
5.嵌套视图

嵌套命名视图 我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。

/settings/emails                                       /settings/profile
+-----------------------------------+                  +------------------------------+
| UserSettings                      |                  | UserSettings                 |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | |  +------------>  | | Nav | UserProfile        | |
| |     +-------------------------+ |                  | |     +--------------------+ |
| |     |                         | |                  | |     | UserProfilePreview | |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
+-----------------------------------+                  +------------------------------+

其中:

  • Nav 只是一个常规组件。
  • UserSettings 是一个视图组件。
  • UserEmailsSubscriptions、UserProfile、UserProfilePreview 是嵌套的视图组件。

(1) UserSettings
用这个路由配置完成该布局:

{
  path: '/settings',
  // 你也可以在顶级路由就配置命名视图
  component: UserSettings,
  children: [{
    path: 'emails',
    component: UserEmailsSubscriptions
  }, {
    path: 'profile',
    components: {
      default: UserProfile,
      helper: UserProfilePreview
    }
  }]
}
6.嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如:
效果图如下,Test界面嵌套子页面Test1,Test2,Test1与Test2可切换

/Test/Test1                     /Test/Test2
+------------------+                  +-----------------+
| Test             |                  | Test            |
| +--------------+ |                  | +-------------+ |
| | Test1      | |  +------------>  | | Test2       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

(1) 路由配置如下

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Test',
      component: Test,
      children: [
        {
          path: '/Test1',
          name: 'Test1',
          component: Test1
        },
        {
          path: '/Test2/:username/:password',
          name: 'Test2',
          component: Test2
        }
      ]
    }
  ]
})

(2) Test路由文件

<template>
  <div class="hello">
    <router-link :to="{ name: 'Test1'}"><p>跳转Test1</p></router-link>
    <router-view></router-view>
  </div>
</template>

<script>
</script>

<style >
</style>

(3) Test1路由文件

<template>
  <div class="hello">
    <p style="margin-top: 20px">我是Test1</p>
    <router-link :to="{ name: 'Test2', params:{ username: 'lss0555',password:'123456'}}"><p>跳转Test2</p></router-link>
  </div>
</template>

<script>
</script>

<style >
</style>

(4) Test2路由文件

<template>
  <div class="hello">
    <p>username: {{ $route.params.username }}</p>
    <p>password: {{ $route.params.password }}</p>
  </div>
</template>

<script>
</script>

<style >
</style>

(5) 效果
输入 localhost:8080
在这里插入图片描述
点击跳转Test1结果为
在这里插入图片描述
点击跳转Test2,结果为
在这里插入图片描述

7.动态路由匹配

1.路由参数传递

模式 匹配路径 $route.params
/user/:username /user/lss { username: ‘lss’ }
/user/:username/:password /user/lss/password/123 { username: ‘lss’, password: ‘123’ }

(1) 在index.js申明组件

import Vue from 'vue'
import Router from 'vue-router'
import Test1 from '@/components/Test1'
import Test2 from '@/components/Test2'

Vue.use(Router)

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

(2) Test1组件

<template>
  <div class="hello">
    <router-link :to="{ name: 'Test2', params:{ username: 'lss0555',password:'123456'}}"><p>跳转Test2</p></router-link>
    <router-link :to="{ name: 'Test2'}"><p>跳转Test2</p></router-link>
  </div>
</template>

<script>
</script>

<style >
</style>

(2) Test2组件

<template>
  <div class="hello">
    <p>username: {{ $route.params.username }}</p>
    <p>password: {{ $route.params.password }}</p>

    <router-link :to="{ name: 'Test1'}"><p>返回Test1</p></router-link>
  </div>
</template>

<script>
</script>

<style >
</style>

(3) 结果:
点击跳转Test2,显示为

username: lss0555

password: 123456

返回Test1

如果没有携带参数,则浏览器会提示需携带参数

vue-router.esm.js?fe87:16 [vue-router] missing param for named route "Test2": Expected "username" to be defined

2.捕获所有路由或 404 Not found 路由
常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):

{
      path: '/user-*',
      name: 'A',
      component: A
    },
    {
      path: '*',
      name: 'A',
      component: A
    }

说明:

  • 当输入一个无效地址,则被定向到路由A中
  • 当输入一个以user-开头路由,则被定向到路由A中

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
8.路由组件传参

1.布尔模式
如果 props 被设置为 true,route.params 将会被设置为组件属性。
(1) index.js

import Vue from 'vue'
import Router from 'vue-router'
import Test from '@/components/Test'
import Test3 from '@/components/Test3'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Test',
      component: Test
    },
    {
      path: '/Test3/:id',
      name: 'Test3',
      props: true,
      component: Test3
    }
  ]
})

(2) Test路由组件

<template>
  <div class="hello">
    <router-link :to="{ name: 'Test3',params:{ id: 'lss0555'} }"><p>跳转Test3</p></router-link>
  </div>
</template>

<script>
</script>

<style >
</style>

(3) Test3路由组件

<template>
  <div class="hello">
    <p>username: {{ $route.params.id }}</p>
  </div>
</template>

<script>
export default {
  props: ['id'],
  mounted () {
    // console.log(this.$route)
    console.log('参数ID:' + this.id)
  }
}
</script>

<style >
</style>
结果

console显示

参数ID:lss0555

2.对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

 {
      path: '/Test3/:id',
      name: 'Test3',
      props: {
        id: 'lss0666'
      },
      component: Test3
    }

这样组件Test3收到的id则为lss0666

3.函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合

  {
      path: '/Test3/:id',
      name: 'Test3',
      props: (route) => ({id: '123456'}),
      component: Test3
  }
9.声明式与编程式的导航
声明式 编程式
< router-link :to="…"> router.push(…)

参考文档

https://router.vuejs.org/zh/guide/

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

组件的属性有:

to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class

三种使用方法

定义组件C

import C from '@/components/C'
export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/C',
      name: 'C',
      component: C
    }
  ]
})
  • 字符串的形式
<router-link to="/C"><p>跳转界面C</p></router-link>

或者

<router-link :to="'C'"><p>跳转界面C</p></router-link>
  • 命名路由的方式
#可以通过this.$route.params.id来取上动态的id
<router-link 
:to="{ name: 'C', params:{ id: this.$route.params.id }}"><p>测试跳转3</p>
</router-link>

(2) 编程式 vue-router push / replace / go 区别

// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
  • this.$router.push()
    跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
this.$router.push({name: 'routerName'})
  • this.$router.replace
    同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
声明式 编程式
< router-link :to="…" replace> router.replace(…)
1. this.$router.push({name: 'routerName', replace: true})
2. this.$router.replace({name: 'routerName'}
  • this.$router.go(n)
    相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面
/ 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

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

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

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
版权声明:本文为u010520146原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010520146/article/details/108314658

智能推荐

spring与redis整合和序列化问题

spring与redis整合 首先用docker下载redis 下载:docker pull redis 运行:docker run -d -p 6379:6379 --name myredis docker.io/redis 连接redis Desktop Manager 然后开始在springboot上开始配置 application.yml: 自动配置好StringRedisTemplate...

CentOS 7配置南大docker镜像

文章目录 CentOS 7配置南大docker镜像 0.帮助页面 1.系统要求 2.卸载旧版本(没有旧版本可跳过) 3.安装方式 4.准备工作 5.可选操作 Stable Test Nightly 6.安装docker引擎 7. (可选)修改配置文件防止与xshell连接冲突 8.启动docker CentOS 7配置南大docker镜像 0.帮助页面 南大docker源:https://mirr...

Qcon演讲纪实:详解如何在实时视频通话中实现AR功能

2018年4月20日-22日,由 infoQ 主办的 Qcon 2018全球软件开发大会在北京如期举行。声网首席 iOS 研发工程师,iOS 端移动应用产品设计和技术架构负责人龚宇华,受邀分享了《基于 ARkit 和 ARcore,在实时视频通话中实现 AR 功能》,在演讲中剖析了 AR 与 VR 差异,ARKit 的工作原理,以及逐步讲解如何基于 ARKit 与声网Agora SDK 创建 AR...

POJ2348 UVa10368 HDU1525 Euclid's Game【博弈】

Euclid's GameTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4106    Accepted Submission(s): 1947 Probl...

使用Breeze.js编写更好的查询

这篇文章是由同行评审Agbonghama柯林斯 。 感谢所有SitePoint的审稿作出SitePoint内容也可以是最好的! 数据量正在迅速发展,他们正在变得越来越复杂,维护。 许多开发人员希望避免由数据问题他们的工作过程中造成的问题和头痛。 一个使我们的工作更轻松的图书馆是Breeze.js 。 在这篇文章中,我们将讨论我们如何能够写出更好的查询与Breeze.js。 但是首先,我们应该知道什...

猜你喜欢

Netty框架构建Nio编程

~~~ 随手点赞,养成习惯 ~~~ 为什么选择Netty框架 Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是首屈一指的。 优点: ① API使用简单,开发门槛低 ②功能强大,预置了多种编解码功能,支持多种主流协议 ③ 定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展; ④性能高,通过与其他业界主流的NIO框架对比,Nett...

【JZOJ5262】【GDOI2018模拟8.12】树(DP,性质题)

Description Solution 首先我们可以知道两个性质:1、路径u-v和路径v-w可以合并为路径u-w;2、路径u1-v1加路径u2-v2和路径u1-v2加路径u2-v1是等价的(就是起始点和终点可以互换) 那么知道这些性质之后就很好做了。我们只用知道每个点多少次做起点和多少次做终点。 我们设f[i]表示满足i子树的需求i上的值要是多少。 那么枚举i的所有儿子,判断a[i]-f[i],...

【String-easy】541. Reverse String II 反转的元素,有反转个数和间隔

1. 题目原址 https://leetcode.com/problems/reverse-string-ii/ 2. 题目描述 3. 题目大意 给定一个字符串,和字符串的间隔k, 这个k表示每k个数反转一次,然后再间隔k个元素再反转k个元素。 4. 解题思路 只要按照间隔去反转就可以了。然后间隔k个元素不反转是通过让i每次递增 2*k完成的。 5. AC代码 6. 相似题型 【1】344. Re...

【C语言笔记结构体】

我们都知道C语言中变量的类型决定了变量存储占用的空间。当我们要使用一个变量保存年龄时可以将其声明为int类型,当我们要使用一个变量保存某一科目的考试成绩时可以将其声明为float。 那么,当我们要做一个学生信息管理系统时,需要保存学生的姓名、学号、年龄等信息,该怎么做呢? 如当要保存三个学生的信息时, 方法一是: 方法二是: 显然,方法二跟更清晰,因为它把name、num、age都集成在一个模板,...

39. Combination Sum 回溯算法简析

LeetCode传送门     这道题要求给你一组正数 C,然后给你一个目标数 T,让你从那组C中找到加在一起等于 T 的那些组合。     例如:给你 [2,3,6,7] 和 7,则返回 [[2,2,3],[7] ] 。      想解决这个问题前,我们首先引入一个新问题,图(树)的遍历问题。  ...