Vue Router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌
安装
npm install vue-router --save
配置
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// 1. 安装插件
Vue.use(VueRouter)
// 3. 配置路由
const routes = [
{
// 前端路由地址 (不含http信息)
path: '/',
name: 'Home',
// 绑定对应组件
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/index',
// 重定向, 意味着当访问 xx/index时,将自动重定向到 xx/ 路由
redirect: '/'
}
]
// 3. 创建VueRouter对象
const router = new VueRouter({
routes,
// 去除路由过程中间的 # 号
mode: 'history'
})
export default router
// 4. 去main.js中导入 该router对象
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
// 导入roter对象
router,
render: h => h(App)
}).$mount('#app')
使用
router-link (路由切换) 、 router-view(对应组件内容占位)
App.vue
<template>
<div id="app">
<div id="nav">
<!-- 点击跳转路由 -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<!-- 实现router-link 切换后 占位显示的内容 -->
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
router-link
router-link 默认渲染出来的是
a
标签
App.vue
<template>
<div id="app">
<div id="nav">
<!-- 点击跳转路由 -->
<router-link to="/">Home</router-link> |
<!-- tag 修改router-link 渲染的标签类型-->
<!-- replace 点了之后不能回退左上角 -->
<!-- active-class 指定 router-link 的类 -->
<router-link to="/about" tag="button" replace active-class="active">About</router-link>
</div>
<!-- 实现router-link 切换后 占位显示的内容 -->
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
.active {
color: red;
}
</style>
通过代码跳转路由
App.vue
<template>
<div id="app">
<div id="nav">
<!-- 点击跳转路由 -->
<router-link to="/">Home</router-link> |
<!-- tag 修改router-link 渲染的标签类型-->
<!-- replace 点了之后不能回退左上角 -->
<!-- active-class 指定 router-link 的类 -->
<router-link to="/about" tag="button" replace active-class="active">About</router-link>
<button @click="toAbout">toAbout</button>
</div>
<!-- 实现router-link 切换后 占位显示的内容 -->
<router-view/>
</div>
</template>
<script>
export default {
methods: {
toAbout: function() {
// this.$router.push('/about')
this.$router.replace('/about')
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
.active {
color: red;
}
</style>
动态路由
路径不确定: user/:id , :id 为不确定值
User.vue
<template>
<div><h1>user Page {{ userId }}</h1></div>
</template>
<script>
export default {
name: 'User',
computed: {
userId() {
// $route, 当前活跃路由, params.属性 该属性为router/index.js中定义的动态路由 :userId userId为属性名
return this.$route.params.userId
}
}
}
</script>
<style>
</style>
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import User from '../views/User'
// 1. 安装插件
Vue.use(VueRouter)
// 3. 配置路由
const routes = [
{
// 前端路由地址 (不含http信息)
path: '/',
name: 'Home',
// 绑定对应组件
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/index',
// 重定向, 意味着当访问 xx/index时,将自动重定向到 xx/ 路由
redirect: '/'
},
// 动态路由
{
// :id 表示该路由id 部分是可变的
path: '/user/:userId',
name: 'User',
component: User
}
]
// 3. 创建VueRouter对象
const router = new VueRouter({
routes,
// 去除路由过程中间的 # 号
mode: 'history'
})
export default router
// 4. 去main.js中导入 该router对象
App.vue
<template>
<div id="app">
<div id="nav">
<!-- 点击跳转路由 -->
<router-link to="/">Home</router-link> |
<!-- tag 修改router-link 渲染的标签类型-->
<!-- replace 点了之后不能回退左上角 -->
<!-- active-class 指定 router-link 的类 -->
<router-link to="/about" tag="button" replace active-class="active">About</router-link>
<button @click="toAbout">toAbout</button>
<!-- 动态绑定 需要变化的路由, -->
<router-link :to="`/user/${userId}`">User</router-link>
</div>
<!-- 实现router-link 切换后 占位显示的内容 -->
<router-view/>
</div>
</template>
<script>
export default {
data() {
return {
userId: 1
}
},
methods: {
toAbout: function() {
// this.$router.push('/about')
this.$router.replace('/about')
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
.active {
color: red;
}
</style>
路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// 1. 安装插件
Vue.use(VueRouter)
const User = () => import(/* webpackChunkName: "about" */ '../views/User.vue')
// 3. 配置路由
const routes = [
{
// 前端路由地址 (不含http信息)
path: '/',
name: 'Home',
// 绑定对应组件
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// 路由懒加载
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/index',
// 重定向, 意味着当访问 xx/index时,将自动重定向到 xx/ 路由
redirect: '/'
},
// 动态路由
{
// :id 表示该路由id 部分是可变的
path: '/user/:userId',
name: 'User',
component: User
}
]
// 3. 创建VueRouter对象
const router = new VueRouter({
routes,
// 去除路由过程中间的 # 号
mode: 'history'
})
export default router
// 4. 去main.js中导入 该router对象
嵌套路由
1. News.vue
<template>
<div><ul>
<li>1</li>
<li>1</li>
</ul></div>
</template>
<script>
export default {
name: "News"
}
</script>
<style>
</style>
2. router/inde.js
定义子路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import User from '../views/User'
// 1. 安装插件
Vue.use(VueRouter)
// 3. 配置路由
const routes = [
{
// 前端路由地址 (不含http信息)
path: '/',
name: 'Home',
// 绑定对应组件
component: Home,
// 子路由
children: [
{
// 子路由不需要加 /
path: "news",
component: () => import('../views/News')
}
]
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// 路由懒加载
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
},
{
path: '/index',
// 重定向, 意味着当访问 xx/index时,将自动重定向到 xx/ 路由
redirect: '/'
},
// 动态路由
{
// :id 表示该路由id 部分是可变的
path: '/user/:userId',
name: 'User',
component: User
}
]
// 3. 创建VueRouter对象
const router = new VueRouter({
routes,
// 去除路由过程中间的 # 号
mode: 'history'
})
export default router
// 4. 去main.js中导入 该router对象
3. Home.vue
使用子路由
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<router-link to="/news"> 子路由 user</router-link>
<router-view></router-view>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
参数传递
- params类型
user/:id -> user/100
this.$route.params
- query类型
user?id=100
this.$route.query
$route
与 $router
$router
: Vue-Router对象$route
: 当前活跃(页面所在)路由
导航守卫(全局)
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import User from '../views/User'
// 1. 安装插件
Vue.use(VueRouter)
// 3. 配置路由
const routes = [
{
// 前端路由地址 (不含http信息)
path: '/',
name: 'Home',
// 绑定对应组件
component: Home,
// 子路由
children: [
{
// 子路由不需要加 /
path: "news",
component: () => import('../views/News')
}
]
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// 路由懒加载
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
// 定义元类数据,用于实现根据路由变换title
meta:{
title: "关于"
}
},
{
path: '/index',
// 重定向, 意味着当访问 xx/index时,将自动重定向到 xx/ 路由
redirect: '/'
},
// 动态路由
{
// :id 表示该路由id 部分是可变的
path: '/user/:userId',
name: 'User',
component: User
}
]
// 3. 创建VueRouter对象
const router = new VueRouter({
routes,
// 去除路由过程中间的 # 号
mode: 'history'
})
// 导航守卫, 前置钩子
router.beforeEach((to, from, next) => {
// 实现标题根据路由进行变化
document.title = to.matched[0].meta.title
next()
})
// 后置钩子
router.afterEach((to, from) => {
console.log(to, from)
})
export default router
// 4. 去main.js中导入 该router对象
keep-alive
缓存,使组件保留状态,避免重新渲染
- include: 只有匹配的组件被缓存
- exclude: 匹配的组件将不被缓存
App.vue
<template>
<div id="app">
<div id="nav">
<!-- 点击跳转路由 -->
<router-link to="/">Home</router-link> |
<!-- tag 修改router-link 渲染的标签类型-->
<!-- replace 点了之后不能回退左上角 -->
<!-- active-class 指定 router-link 的类 -->
<router-link to="/about" tag="button" replace active-class="active">About</router-link>
<button @click="toAbout">toAbout</button>
<!-- 动态绑定 需要变化的路由, -->
<router-link :to="`/user/${userId}`">User</router-link>
</div>
<!-- keep-live 缓存 -->
<keep-alive exclude="About,User">
<!-- 实现router-link 切换后 占位显示的内容 -->
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
data() {
return {
userId: 1
}
},
methods: {
toAbout: function() {
// this.$router.push('/about')
this.$router.replace('/about')
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
.active {
color: red;
}
</style>