目录
(一) Vue Router 路由概述
1. 路由
路由: 是网络工程一个术语, 通过互联的网络把信息从 源地址 传输到 目的地址 的活动, 在此存在一个映射关系表: { 源地址1: 目的地址1, 源地址2: 目的地址2, …}
后端路由: 服务器(JSP技术)直接生产渲染好对应的HTML页面, 返回给客户端进行展示, 后端(服务器) 处理URL和页面之间的映射关系
前端路由: SPA(单页面应用)页面, 在前后端分离的基础上加了一层前端路由, 前端处理URL和页面(组件)之间的映射关系. URL改变时, 页面不进行整体的刷新, 只是通过前端路由显示对应的组件
实现URL改变, 页面不刷新的方式:
- 改变URL的hash值
// 会将 http://localhost:8080/ 换成 http://localhost:8080/#poo location.hash = 'poo'
- HTML5的history模式:
- pushState(state, title, url): 入栈一个新历史纪录的地址(可回退)
// 会将 http://localhost:8080/ 换成 http://localhost:8080/poo history.pushState({}, '', 'poo')
- back(): 出栈栈顶历史纪录的地址, 相当于回退
// 回退: 会将 http://localhost:8080/poo 回退 http://localhost:8080/ history.back()
- forward(): URL前进一次
// http://localhost:8080/ 将前进成 http://localhost:8080/poo history.forward()
- repleacState(state, title, url): 替换栈顶历史纪录的地址, 无法回退
history.pushState({}, '', 'poo')
- go(num):
num为正数时: 前进访问栈中所有的历史纪录的地址, 相当于执行 num次 forward()
num为负数时: 回退访问栈中所有的历史纪录的地址, 相当于执行 num次 historyback()
// 相当于执行了一次 history.back() history.go(-1)
2. Vue Router
Vue Router: 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌
- Vue Router 是基于路由和组件的
- 路由用于设定访问路径, 将路径和组件映射起来
- 在Vue Router的单页面应用中, 页面的路径的改变就是组件的切换
(二) Vue Router 基本使用
1. vue-router安装
通过命令安装vue-router依赖, 也可以通过VueCli脚手架安装
npm install vue-router --save
2. vue-router基本架构
新建文件/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router' // 导入VueRouter插件对象
// 1. 通过Vue.use(插件), 安装插件
Vue.use(VueRouter)
// 2.创建VueRouter对象并导出, 以供Vue实例使用
const routes = [];
export default new VueRouter({
routes
})
Vue实例使用router对象(main.js)
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
3. vue-router映射配置
path路径 映射到 component组件
import Home from '../components/Home'
import About from '../components/About'
const routes = [
// {path: 路径, component: 组件}
{ path: '/home', component: Home},
{ path: '/about', component: About}
]
4. 路由使用和呈现
使用路由:
- <router-link to=“path路径”><router-link>: 使用 router-link 组件(vue-router全局组件)来导航显示跳转链接
- to属性: 路由跳转path路径
- tag属性: router-link 最终渲染的标签, 默认会被渲染成一个
<a>
标签(tag = “a”). - replace属性: 是否使用 history.replaceState() 方法
<div id="app"> <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> <router-view /> </div>
- <router-view></router-view>: 路由出口, 路由匹配到的组件将渲染在此处
<router-view />
路由默认路径:
const routes = [
// 匹配根路径, 重定向到 '/home' 路径对应的组件
{ path: '/', redirect: '/home'},
{ path: '/home', component: Home},
{ path: '/about', component: About}
]
vue-router默认使用修改URL的hash值, 来实现页面不刷新方式, 修改成HTML5的history模式
export default new VueRouter({
routes,
mode: 'history'
})
通过代码跳转路由: $router对象在vue-router内部定义
this.$router.push('路径')
this.$router.replace('路径')
(三) 动态路由
在某些情况下, 一个页面的path路径可能是不确定的, 或者说, 把某种模式配到的所有路由, 全都映射到同个组件, 如: 进入用户界面组件时, 希望映射的路径为 /user/100010 或 /user/100011, /use是完全匹配的, user后面跟上的是用户id, 我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果
格式: {path: ‘/url/:参数名’, component: cmp}
import User from '../components/User'
const routes = [
... ,
{path: '/user/:id', component: User}
]
<div id="app">
<router-link to="/home" >首页</router-link>
<router-link to="/about">关于</router-link>
<router-link :to="'/user/' + userId">用户</router-link>
<router-view />
</div>
<script>
export default {
name: 'App',
data() {
return {
userId: 10010
}
}
}
</script>
页面获取路由的动态路径参数: 通过this.$route.params.参数名对象获取
this.$route: 当前选中路由对象
<div>
<h3>用户-标题</h3>
<p>用户ID: {{$route.params.userId}}</p>
</div>
(四) 路由组件传参
路由组件传参的方式:
- params类型
- 配置路由格式: /router/:参数名
- 传递方式: /router/10010
- 接收方式: this.$route.params.参数名
- query类型
- 配置路由格式: /router (普通配置)
- 传递方式: { path: ‘’, query: {} }
- 接收方式: this.$route.query
<!-- App.vue --> <router-link :to="{path: '/about', query: {username: 'zhangsan', age: 20}}">关于</router-link> <!-- About.vue --> <div> <h3>关于-标题</h3> <p>关于-内容</p> <p>{{this.$route.query.username}}</p> <p>{{this.$route.query.age}}</p> </div>
$router 与 $route 区别:
- $router对象是 全局路由对象router
- $route对象是当前活跃(url)路由对象
所有的组件都继承自Vue原型(prototype), 在Vue.prototype中定义的变量、函数, 在任何vue实例中都可以使用. $router 和 $route 对象在Vue-Router源码中通过Vue.prototype定义了.
(五) 嵌套路由
嵌套路由又称为子路由, 父级路由可以拥有多个子级路由
嵌套路由使用步骤:
- 在route中创建对应的子组件, 并在路由映射上配置对应的子路由
- 在子组件内部使用<router-view>标签呈现
比如在 /home首页路由中, 还存在两个子级路由: /home/news首页新闻路由 和 /home/message首页消息路由, 映射关系如下:
const HomeNews = () => import('../components/HomeNews')
const HomeMessage = () => import('../components/HomeMessage')
const routes = [
... ,
{
path: '/home',
component: Home,
// 配置子路由, 默认显示HomeNews组件
children: [
{
path: '/',
component: HomeNews
},
{
path: 'news',
component: HomeNews
},
{
path: 'message',
component: HomeMessage
}
]
}
]
<div>
<h3>首页-标题</h3>
<p>首页-内容</p>
<router-link to="/home/news">新闻</router-link>
<router-link to="/home/message">消息</router-link>
<router-view></router-view>
</div>
(六) 导航守卫
导航守卫: vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航. 即, 在路由地址跳转过程中会触发一些钩子函数, 在这些函数中可以 取消跳转(url), 也可以指定跳转路径(路由地址).
1. 全局守卫: 一旦路由跳转, 就会触发全局守卫
- 全局前置守卫钩子函数: 在路由还未跳转到目的路由时触发, 在此函数中可以 取消跳转 或 指定路由跳转
import router from './router' /* to: 即将要进入的目标 路由对象 from: 当前导航正要离开的路由 */ router.beforeEach((to, from, next) => { next() // 执行下一个钩子函数, 执行完全部钩子函数, 跳转路由 next(false) // 取消跳转, URl地址返回 from 路由地址 next('/') // 跳转到指定路由地址 })
- 全局后置守卫钩子函数: 在路由跳转到目的路由后触发
router.afterEach((to, from) => { })
2. 路由独享的守卫: 跳转到指定路由才会触发的钩子函数
const routes = [
... ,
{
path: '/about',
component: About,
beforeEnter: (to, from, next) => {
}
}
]
3. 组件内的守卫: 跳转到指定组件才会触发的钩子函数
在About.vue文件中
export default {
name: 'About',
beforeRouteEnter(to, from, next) {
// 访问该组件前调用的钩子函数, 组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 当前路由改变, 但 是该组件被复用时调用的钩子函数(如: /foo/1 跳转到 /foo/2), 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用的钩子函数, 可以访问组件实例 `this`
}
}
(七) 路由懒加载
当打包构建应用时, 有依赖的js文件会打包同一个js文件包, 文件包会非常大, 在客户端向静态资源服务器请求时, 一次性加载会花费一定时间, 影响页面的加载
路由懒加载: 结合 Vue 的异步组件和 Webpack 的代码分割功能, 把不同路由对应的组件分割成不同的代码块打包, 当路由被访问的时候才加载对应的组件打包代码 (一个路由的懒加载对应一个打包的js文件)
路由懒加载三种方式:
- 结合Vue的异步组件和Webpack的代码分割 来导入组件
const HomeComponent = resolve => { requrie.ensure(['../components/Home.vue']), () => { resolve(require('../components/Home.vue')) } }
- AMD写法, 导入组件
const HomeComponent = resolve => require(['../components/Home.vue'], resolve)
- ES6语法, 导入组件 (推荐使用)
const HomeComponent = () => import('../components/Home.vue')
(八) keep-alive 组件
keep-alive: 是Vue内置的一个组件, 可以使被包含的组件保留状态, 避免重新渲染.
keep-alive组件的属性:
- includer: 字符串或正则表达式, 匹配的组件会被缓存 (组件导出的name属性)
- excluder: 字符串或正则表达式, 匹配的组件不会被缓存 (组件导出的name属性)
<keep-alive includer="Home,User" exclude="About" >
<router-view></router-view>
</keep-alive>