vue 的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。在vue-router 的单页面应用中,路径的切换实际上就是组件的切换,即路由就是SPA(单页应用)的路径管理器。
vue-router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,包含的功能有:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
1、安装
- 直接下载 / CND :https://unpkg.com/vue-router/dist/vue-router.js
// 在 Vue 后面加载 vue-router,会自动安装
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
- NPM安装
npm install vue-router
模块化工程中的使用:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
2、基本使用
- JavaScript
<script>
// 1、定义(路由)组件
var login = {template: "<h3>Login</h3>"}
var register = {template: "<h3>Register</h3>"}
// 2、定义路由对象
var routerObj = new VueRouter({
// routes 路由匹配规则
routes: [
// path 监听的路由链接地址
// component path映射到的组件, redirect 重定向地址
{path: '/', redirect: '/login'},
{path: '/login', component: login},
{path: '/register', component: register}
]
})
// 3、创建和挂载根实例
var vm = new Vue({
el: "#app",
router: routerObj
})
</script>
- HTML
<div id="app">
<!-- 使用 router-link 组件来导航 -->
<!-- to 指定链接 -->
<!-- tag 指定渲染成的标签,默认为`<a>`标签 -->
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<!-- 路由出口,路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
vue-route 路由导航时,使用的是URL的hash(‘#’)(‘#’ 代表网页中的一个位置,其右边的字符,就是该位置的标识符)。由于HTTP请求中不包含 ‘#’ ,所以在单页面应用中进行路由时,不会重新加载网页。
3、设置选中路由样式
可以通过设置路由的默认class(“router-link-active”)样式,来设置选中路由的显示样式。
<style>
.router-link-active {
background-color: red;
}
</style>
也可以通过更改 Router 的 “linkActiveClass” 选项,来自定义要使用的样式名称,即可以引入外部class样式。
// 自定义样式
.myActive {
background-color: green;
}
var routerObj = new VueRouter({
routes: [...],
// 设置路由激活样式名称
linkActiveClass: 'myActive'
})
4、路由切换动画
路由切换的动画引入,与组件切换的类似,将路由视图组件放入动画组件中即可。
- 动画样式:
<style>
.v-enter,.v-leave-to {
opacity: 0;
transform: translateX(80px);
}
.v-enter-active, .v-leave-active{
transition: all 0.4s ease;
}
</style>
- 路由加入动画:
<transition mode="out-in">
<router-view></router-view>
</transition>
5、路由传参
- query方式传参:
在 <router-link> 标签的 ‘to’ 属性中,使用 url 路由地址直接拼接参数及值来传参。
<router-link to="/login?id=10&name=Tom">登录</router-link>
在组件的当前router跳转对象(this.$route)的 query 对象中,获取传入参数的值。
var login = {
template: "<h3>Login</h3>",
created(){
console.log(this.$route.query.id + " " + this.$route.query.name)
}
}
- params 方式传参:
在路由对象的 routes 选项的 path 属性中,定义要传入的参数,再在 <router-link> 的 url 中直接传值来对参数进行正则匹配。
<router-link to="/login/10/Tom">登录</router-link>
var routerObj = new VueRouter({
routes: [
...
{path: '/login/:id/:name', component: login},
]
})
在组件的当前router跳转对象(this.$route)的 params 对象中,获取传入参数的值。
console.log(this.$route.params.id + " " + this.$route.params.name)
6、路由嵌套
URL 中各段动态路径可以按某种结构,来对应嵌套的各层组件。也就是说,一个被渲染组件可以包含自己的嵌套 <router-view>,而要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../vue.min.js"></script>
<script src="../vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/account">account</router-link>
<!-- 嵌套路由最顶层的出口 -->
<router-view></router-view>
</div>
<template id="account">
<div>
<h3>Account组件</h3>
<!-- 路径名包含父路径,方便用户辨识 -->
<router-link to="/account/login">登录</router-link>
<router-link to="/account/register">注册</router-link>
<!-- 嵌套路由 -->
<router-view></router-view>
</div>
</template>
<script>
var account = {
template: "#account"
}
var login = {template: "<h3>Login</h3>",}
var register = {template: "<h3>Register</h3>"}
var routerObj = new VueRouter({
routes: [
{
path: '/account',
component: account,
// 配置children选项
children: [
// path 前面加 '/' 表示根路径
// 匹配成功才会渲染在account的 <router-view> 中
{path: 'login', component: login},
{path: 'register', component: register}
]
},
]
})
var vm = new Vue({
el: "#app",
router: routerObj
})
</script>
</body>
</html>
7、命名视图
如果想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这时候就需要命名视图了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../vue.min.js"></script>
<script src="../vue-router.js"></script>
<style>
.header {
background-color: orange;
height: 80px;
}
.container {
display: flex;
height: 600px;
}
html, body, h1 {
margin: 0;
padding: 0;
}
.left {
flex: 2;
background-color: lightgreen;
}
.main {
flex: 8;
background-color: lightpink;
}
</style>
</head>
<body>
<div id="app">
<!-- name 指定组件名称 -->
<router-view name="header"></router-view>
<div class="container">
<router-view name="left"></router-view>
<router-view name="main"></router-view>
</div>
</div>
<script>
var header = {template: "<h1 class='header'>Header</h1>"}
var left = {template: "<h1 class='left'>Left</h1>"}
var main = {template: "<h1 class='main'>Main</h1>"}
var routerObj = new VueRouter({
routes: [
// 同级多个视图,使用 components 对象存储多个组件
{path: '/', components: {
'header':header,
'left': left,
'main': main
}},
]
})
var vm = new Vue({
el: "#app",
router: routerObj
})
</script>
</body>
</html>
参考链接: