23.Vue路由管理器:Router(基础篇)

简介

Vue Router 是 Vue.js 官方的路由管理器。时下流行单页面应用,需要用到路由在模块之间切换。路由本身不发请求。

Vue Router 包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为
     

配置

Vue Router配置文件如下。

//src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue' //采用外部引入后使用方式

Vue.use(VueRouter)

  const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue') //采用直接导入方式
  }
]

const router = new VueRouter({
  //mode: 'history', //使用history模式的话,后端要做额外配置
  //base: '/app/', //那么所有的请求都会在url之后加上/app/基路径
  routes
})

export default router //导出后供main.js导入使用

main.js使用router:

//main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router' //导入

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

 

History 模式

History 模式可以让路由地址更美观:

//Hash 模式
http://localhost:8080/#/about
//History 模式
http://localhost:8080/about

要支持此模式,后端需要做额外配置,以nginx为例。

location / {
  try_files $uri $uri/ /index.html;
}

 

简单路由

vue依靠router-link和router-view展示视图。router-link其实是一个有样式的a标签,router-link指向(to=‘xxx’)的路径,将决定router-view展示的视图内容。

// App.vue
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">首页</router-link> |
      <router-link to="/about">关于</router-link>
    </div>
    <router-view/>
  </div>
</template>

// views/Home.vue
<template>
  <div class="home">
    <h1>这是首页面</h1>
  </div>
</template>

// views/About.vue
<template>
  <div class="about">
    <h1>这是页面2</h1>
  </div>
</template>

运行:
在这里插入图片描述
 

this.$router

通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由。
this.$router 和 router 使用起来完全一样。我们使用 this.$router 的原因是我们并不想在每个独立需要封装路由的组件中都导入路由

//假设某.vue
export default {
  computed: {
    username() {
      return this.$route.params.username //取地址中的动态路由参数
    }
  },
  methods: {
    goBack() {
      window.history.length > 1 ? 
      this.$router.go(-1) : this.$router.push('/') //回退:跳转,history栈添加一个记录
    }
  }
}

 

动态路由

当需要把某种模式匹配到的所有路由,全都映射到同个组件时,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果。比如,地址中通过id区分不同文章。

// router/index.js
  {
    path: '/new/:id', // 动态路径参数 以冒号开头
    name: 'New',
    component: () => import('../views/New.vue')
  },
  
//New.vue
<template>
	<div class="new">
	  <h1>新闻 {{$route.params.id}}</h1>
	</div>
</template>

<script>
	export default{
		mounted() {
			console.log(this);
		}
	}
</script>

运行,假设路径不带后面的“/8”,页面html会展示空白,log也不会打印。
在这里插入图片描述
如果有多个参数需要获取。

// router/index.js
  {
    path: '/new/id:id/user:user', // 动态路径参数 以冒号开头
    name: 'New',
    component: () => import('../views/New.vue')
  },
  
//New.vue
<template>
	<div class="new">
	  <h1>新闻 {{$route.params.id}}</h1>
      <h1>作者 {{$route.params.user}}</h1>
	</div>
</template>

<script>
	export default{
		mounted() {
			console.log(this);
		}
	}
</script>

运行:
在这里插入图片描述
 

响应路由参数的变化

当使用路由参数时,例如从 /user95 导航到 /user63,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用,所以上面的页面不会再调用mounted()打印

//New.vue	
 export default {
		mounted() {
			console.log(this);
		},
		watch: {
			// 对路由变化作出响应
			$route(to, from) {
				console.log(to);
				console.log(from);
			}
		}
	}

再次从 /user95 导航到 /user63,没有调用mounted()打印,但打印了from to
在这里插入图片描述
 

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件。
在这里插入图片描述
使用 children[] 配置子路由,可以用 / 作为子路由根路径。

// router/index.js
 	{
		path: '/father/id:id',
		//name: 'Father', //子路由有‘/’,所以不用name
		component: () => import('../views/Father.vue'),
		children: [{
				// 当 /father/id:id/child1 匹配成功,Child1.vue 会被渲染在 Father.vue 的 <router-view> 中
				path: 'child1',
				component: () => import('../views/Child1.vue'),
			},
			{
				path: 'child2',
				component: () => import('../views/Child2.vue'),
			},
			{
				path: '/', //作为根路径
				component: () => import('../views/Child0.vue'),
			},

		]
	},

父子页面:

//Child1.vue
<template>
	<div>子页面1</div>
</template>

//Child2.vue
<template>
	<div>子页面2</div>
</template>

//Child0.vue
<template>
	<div>子路由根路径</div>
</template>

运行:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
 

命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,这个时候命名视图就派上用场了。

// router/index.js
	{
		path: '/brother',
            //name: 'Brother',//子路由有‘/’,所以不能再有name
		component: () => import('../views/Brother.vue'),
		children: [{
			path: '/', //同级路由path要为'/',然后在父级vue中配置多个<router-view/>
			components: {
				default: () => import('../views/Brother0.vue'),
				name1: () => import('../views/Brother1.vue'),
				name2: () => import('../views/Brother2.vue'),
			}
		}]
	},
//Brother.vue
<template>
	<div>
		<router-view></router-view>
		<router-view name="name1"></router-view>
		<router-view name="name2"></router-view>
	</div>
</template>

//Brother0.vue
<template>
	<div>brother0</div>
</template>
//Brother1.vue
<template>
	<div>brother1</div>
</template>
//Brother2.vue
<template>
	<div>brother2</div>
</template>

运行:
在这里插入图片描述
 

编程式导航

编程式导航有三种方法:

  1. this.$router.push():跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
  2. this.$router.replace():同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
  3. this.$router.go(n):相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数等同于forward(),负数等同于back()。

router.push

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

声明式编程式
<router-link :to="…">router.push(…)

router.push(location, onComplete?, onAbort?)方法的使用。

// 字符串
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 会被忽略,需要提供路由的 name 或手写完整的带有参数(query)的 path。

// router/index.js
const userId = '123'

//完整path
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
//path+params,params,被忽略
router.push({ path: '/user', params: { userId }}) // -> /user  // 这里的 params 不生效
//path拼接参数或者增加query字段
router.push({ path: '/user?userId=123'}}) // -> /user?userId=123
router.push({ path: '/user', query: { userId:'123' }}) // -> /user?userId=123

router.replace

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
router.replace(location, onComplete?, onAbort?)

声明式编程式
<router-link :to="…" replace>router.replace(…)

router.go

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

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

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

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

 

重定向

//从 /a 重定向到 /b
{ path: '/a', redirect: '/b' }

//重定向的目标也可以是一个命名的路由
{ path: '/a', redirect: { name: 'foo' }}

//甚至是一个方法,动态返回重定向目标
{ path: '/a', redirect: to => {
  // 方法接收 目标路由 作为参数
  // return 重定向的 字符串路径/路径对象
}}

 

路由组件传参

在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。可以使用 props 将组件和路由解耦。

<div>id:{{ $route.params.id }}</div>

布尔模式

如果routes对象中的 props 属性被设置为 true,route.params 将会被设置为组件属性。

// Container.vue
<template>
	<div>id:{{id}}</div>
</template>
<script>
	export default {
		props: ['id'],
	}
</script>

// router/index.js
const router = new VueRouter({
  routes: [
	{
        path: '/container/:id',
        name: 'Container',
        props: true ,
        component: () => import('../views/Container.vue')
	}

    // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

控制台props 中有id:
在这里插入图片描述

对象模式

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

	{
		path: '/container/:id',
		name: 'Container',
		props: {
			mm : 999
		} ,
		component: () => import('../views/Container.vue')
	}

 

函数模式

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

	{
		path: '/container/:id',
		name: 'Container',
		props: (route) => ({
			id: route.params.id,
			mm: 985
		}),
		component: () => import('../views/Container.vue')
	}

在这里插入图片描述
 

相关资料

Vue Router官网

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值