Vue-Router
摘要
vue-router,顾名思义,就是用来处理 Vue 中路由的工具。在此献上官网
# 介绍
什么是路由?其实路由可以简单地理解为:路由就是根据网址的不同,返回不同的内容给用户
在开发 Vue 项目的时候,就是使用这个工具来进行项目的路由管理
# 多页面应用 VS 单页面应用
提及路由,就会想到多页面和单页面的问题,这里稍微了解一下
多页面应用
- 特点:页面跳转是直接返回 HTML 文件
- 优点:首屏时间快,SEO 效果好
- 缺点:页面切换慢
单页面应用
- 特点:使用 JS 监听路由来动态渲染页面
- 优点:页面切换快
- 缺点:首屏时间稍慢,SEO 差
- 解决方案:使用 vue-ssr 服务端渲染来解决首页渲染慢的问题
# 目录
在已经搭建完 Vue-CLI 的情况下再继续新建文件,目录结构如下
├─src
| ├─App.vue
| ├─main.js
| ├─router
| | └index.js
| ├─components
| | ├─A.vue
| | ├─B.vue
| | └HelloWorld.vue
| ├─assets
| | └logo.png
# 使用方法
# 引入 vue-router
由于在搭建 vue-cli 中已经安装好了 vue-router,所以就不用再多做配置。
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
# 引入定义路由
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import A from '@/components/A'
import B from '@/components/B'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B
}
]
})
# 修改 .vue 文件
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
HelloWorld.vue
这里的 A.vue
和 B.vue
只需要简单的模板即可
<template>
<div>
<router-link to='/A'>toA</router-link>
<router-link to='/B/1' tag='p'>toB</router-link>
</div>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
<style scoped>
</style>
在 .vue 文件中
- 使用
<router-view/>
来使路由生效,显示当前路由地址所对应的内容 - 使用
<router-link>
代替 a 标签进行页面跳转。但是<router-link>
可以使用 tag 属性变成其他标签
# 基本参数讲解
在 router/index.js 中
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import A from '@/components/A'
import B from '@/components/B'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B
}
]
})
- routes 数组,可以对每个路由进行配置
- path 可以用来指定路由地址,可以用
:
来定义一个变量名,从而使用param
路由,在组件内可以使用this.$route
来查看。 - name 开发者可以自己定义,在编程式导航中需要用到
- component 则是路由对应的组件
- path 可以用来指定路由地址,可以用
还有更多的参数可以参考这里
# 动态路由
对于参数式如何传递的,vue-router 提供了一种动态路由的方式,如果你够细心的话,就会发现,router/index.js 中对于 B 组件的路由如此设置的 —— 使用 :
来绑定传递的参数
{
path: '/B/:id',
name: 'B',
component: B
}
那么如何获取传递的参数?
B.vue
<template>
<div>
B{{ id }}
</div>
</template>
<script>
export default {
name: 'B',
data () {
return {
id: this.$route.params.id // 获得传递的参数
}
}
}
</script>
<style scoped>
</style>
# 编程式导航
仅仅使用动态路由来进行参数传递其实并不满足于开发的需求,所以就有编程式导航的出现
如何使用编程式导航,可以查看以下示例
A.vue
<template>
<div>
<p>A</p>
<div>
<button @click='handleClick'>Click to B</button>
<button @click='handleClickBack'>Click to Back</button>
</div>
</div>
</template>
<script>
export default {
name: 'A',
methods: {
handleClick () {
// this.$router.push('/B/5')
this.$router.push({
name: 'B',
params: {
id: 6
}
})
},
handleClickBack () {
this.$router.go(-1)
}
}
}
</script>
<style scoped>
</style>
# 细节点优化
# 去除路由中的哈希值
vue-router
默认hash
模式 —— 使用 URL 的hash
来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。- 如果不想要很丑的
hash,我们可以用路由的
history
模式, - 在
router/index.js
的new Router
对象里配置一个mode:'history'
来去除路由中的哈希值 - 因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问就会返回 404,所以需要后端进行相对应的配置,请点击这里进行查看
# 过渡动效
<router-view>
是基本的动态组件,所以我们可以用 <transition>
组件给它添加一些过渡效果:
App.vue
<template>
<div id="app">
<transition>
<router-view/>
</transition>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: 1s opacity;
}
</style>
# 路由懒加载
当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const A = () => import('@/components/A')
const B = () => import('@/components/B')
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B
}
]
})
# 404 优化
多定义一个 notFound
的组件
notFound.vue
<template>
<div>
404
</div>
</template>
<script>
export default {
name: 'notFound'
}
</script>
<style scoped>
</style>
然后再 router/index.js 中进行配置
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const A = () => import('@/components/A')
const B = () => import('@/components/B')
const notFound = () => import('@/components/notFound')
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B
},
{
path: '/*', //这里会把不存在的路由全部跳转到这个组件中
name: 'notFound',
component: notFound
}
]
})
# 路由解耦
在获取动态路由的参数的时候,使用 this.$route.params.id
来获取参数的,但是这样耦合性不好,vue-router 提供了一种 props 的方式来传递参数。请看以下示例
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const A = () => import('@/components/A')
const B = () => import('@/components/B')
const notFound = () => import('@/components/notFound')
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B,
props: true
},
{
path: '/*',
name: 'notFound',
component: notFound
}
]
})
B.vue
<template>
<div>
B{{ id }}
</div>
</template>
<script>
export default {
name: 'B',
props: ['id']
// data () {
// return {
// id: this.$route.params.id
// }
// }
}
</script>
<style scoped>
</style>
# 滚动行为
使用 scrollBehavior 参数,在按下 后退/前进 按钮时,就会像浏览器的原生表现那样
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const A = () => import('@/components/A')
const B = () => import('@/components/B')
const notFound = () => import('@/components/notFound')
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/A',
name: 'A',
component: A
},
{
path: '/B/:id',
name: 'B',
component: B,
props: true
},
{
path: '/*',
name: 'notFound',
component: notFound
}
],
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
// return 期望滚动到哪个的位置
return { x: 0, y: 0 }
}
}
})
# 结语
关于 Vue-Router 的总结就到这里,其实并不是很详细,而且还有嵌套路由和导航守卫者两个方面没有涉及到,但这是我个人觉得开发中比较实用的部分,就在此做下笔记,进行学习总结,更多有需要的部分可以到 Vue-Router 的官网上进行查看