四. Vue-Router
路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动. — 维基百科
1.1. 后端路由和前端路由
- 后端渲染/后端路由
- 前后端分离
- SPA/前端路由
后端渲染: 服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。比如:jsp页面
前端渲染: 浏览器中显示的网页中的大部分内容,都是由前端写的 js 代码在浏览器中执行,最终渲染出来的网页。(后端返回JSON数据,前端利用预先写的html模板,循环读取JSON数据,拼接字符串,并插入页面。)
后端路由: 浏览器在地址栏中切换不同的 url 时,每次都向后台服务器发出请求,服务器响应请求,服务器渲染好整个页面, 并且将页面返回给客户端。
前端路由: 核心-改变URL,但是页面不进行整体的刷新。
1.2. SPA页面
SPA:单页面富应用,整个网页只有一个html页面。
SPA最主要的特点就是在前后端分离的基础上加了一层前端路由.
前端路由的核心是改变URL,但是页面不进行整体的刷新。
1.3. URL的hash
URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新.
location.href
"http://192.168.1.101:80/"
location.hash = '/foo'
"http://192.168.1.101:80/#/foo"
复制代码
1.4. HTML5的history模式
- pushState
- back
- forward
- replaceState
- go
history.pushState({},'','/foo')
location.href
"http://192.168.1.101:80/foo"
history.replaceState({},'','/foo')
location.href
"http://192.168.1.101:80/foo"
"http://192.168.1.101:80/foo"
history.go(-1)
location.href
"http://192.168.1.101:80/"
history.go(1)
"http://192.168.1.101:80/foo"
复制代码
1.5. Vue Router
vue-router是基于路由和组件的
- 路由用于设定访问路径, 将路径和组件映射起来.
- 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.
1.6. 安装和使用路由
第一步:导入路由对象,并且调用 Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例
import Vue from 'vue'
import VueRouter from 'vue-router'
路由懒加载
const Home = () => import('../components/Home.vue')
const About = () => import('../components/About.vue')
const Message = () => import('../components/Message.vue')
const news = () => import('../components/news.vue')
Vue.use(VueRouter)
使用vue-router的步骤:
第一步: 创建路由组件
第二步: 配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过<router-link>和<router-view>
// 定义路由
const routers = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home,
// 嵌套路由
children: [
{
path: 'message',
component: Message,
},
{
path: 'news',
component: News,
},
{
path: '',
redirect: 'message'
}
]
},
{
path: '/about',
component: About
}
]
// 创建router实例
const router = new VueRouter({
routers,
// 使用HTML5的history模式
mode: 'history'
// 修改active-class属性的默认类名(router-link-active)
LinkActiveClass: 'active'
})
// 导出router实例
export default router
// 挂载到vue实例
new Vue({
el: '#app',
router,
render: h => h(APP)
})
<router-link>: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个<a>标签.
<router-view>: 该标签会根据当前的路径, 动态渲染出不同的组件.
网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和<router-view>处于同一个等级.
在路由切换时, 切换的是<router-view>挂载的组件, 其他内容不会发生改变.
复制代码
1.7. router-link 其他属性
- to:, 属性: to, 用于指定跳转的路径.
- tag:tag可以指定之后渲染成什么组件, 比如上面的代码会被渲染成一个
- 元素, 而不是
- replace:replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中
- active-class:当对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置LinkActiveClass可以修改默认的名称.
- 在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类.
- 但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.
1.8. 页面路由跳转
<button @click="linkToHome">首页</button>
<script>
export default {
name: 'App',
methods: {
linkToHome() {
this.$router.push('/home')
}
}
}
</script>
复制代码
1.9. 动态路由
1.91. params的类型
- 配置路由格式: /router/:id
- 传递的方式: 在path后面跟上对应的值
- 传递后形成的路径: /router/123, /router/abc
//拿到用户名(userId是自己router中定义的路径)
{
path: '/user/:userId',
component: User
}
<router-link to="/user/123">用户</router-link>
<div>
<h3>{{$route.params.userId}}</h3>
</div>
{{this.$route.params.userId}}
复制代码
1.92. query的类型
- 配置路由格式: /router, 也就是普通配置
- 传递的方式: 对象中使用query的key作为传递方式
- 传递后形成的路径: /router?id=123, /router?id=abc
获取参数
{{$route.params}}
{{$route.query}}
复制代码
1.93. 两种传递参数的方式
传递参数方式一:
传递参数方式二: JavaScript代码
1.94. router是有区别的
-
router.push方法
-
$route为当前router跳转对象里面可以获取name、path、query、params等
2.0. 路由的懒加载
作用:将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候,才加载对应的组件。
方式一: 结合Vue的异步组件和Webpack的代码分析.
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
方式二: AMD写法
const About = resolve => require(['../components/About.vue'], resolve);
方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import('../components/Home.vue')
复制代码
2.1. 嵌套路由
2.2. 导航守卫
- vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.
- vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.
首先, 我们可以在钩子当中定义一些标题, 可以利用meta来定义
其次, 利用导航守卫,修改我们的标题.
const routers = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home,
meta: {
title: '首页'
}
},
{
path: '/about',
component: About,
title: '关于'
}
]
const router = new VueRouter({
routers,
})
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title;
next()
})
export default router
导航钩子的三个参数解析:
to: 即将要进入的目标的路由对象.
from: 当前导航即将要离开的路由对象.
next: 调用该方法后, 才能进入下一个钩子.
复制代码
2.3. keep-alive
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
- 两个属性:
- include – 字符串或正则表达,只有匹配的组件会被缓存
- exclude – 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存。
通过create声明周期函数来验证。
2.4. TabBar案例
-
如果在下方有一个单独的TabBar组件,你如何封装
- 自定义TabBar组件,在APP中使用
- 让TabBar出于底部,并且设置相关的样式
-
TabBar中显示的内容由外界决定
- 定义插槽
- flex布局平分TabBar
-
自定义TabBarItem,可以传入 图片和文字
- 定义TabBarItem,并且定义两个插槽:图片、文字。
- 给两个插槽外层包装div,用于设置样式。
- 填充插槽,实现底部TabBar的效果
-
传入 高亮图片
- 定义另外一个插槽,插入active-icon的数据
- 定义一个变量isActive,通过v-show来决定是否显示对应的icon
-
TabBarItem绑定路由数据
- 安装路由:npm install vue-router —save
- 完成router/index.js的内容,以及创建对应的组件
- main.js中注册router
- APP中加入组件
-
点击item跳转到对应路由,并且动态决定isActive
- 监听item的点击,通过this.$router.replace()替换路由路径
- 通过this.$route.path.indexOf(this.link) !== -1来判断是否是active
-
动态计算active样式
- 封装新的计算属性:this.isActive ? {‘color’: ‘red’} : {}
代码实现