目录
3.3.1全局后置钩子函数(router.afterEach)
1、认识路由
1.1什么是路由?
路由( routing )就是通过互联的网络把信息从源地址传输到目的地址的活动.---维基百科
路由提供了两种机制:路由和转送。
(1) 路由是决定数据包从来源到目的地的路径。
(2)转送将输入端的数据转移到合适的输出端。
路由器中的路由表决定了数据包的指向。
1.2前端渲染和后端渲染
1.2.1后端渲染阶段:jsp
是html+css+java的组合,用户请求服务端的数据的时候会将数据和html和css组合成网页,将该网页传递到前端浏览器,此时浏览器接受到的就是后端渲染好的网页了。也就是说服务器直接生产渲染好的页面返回到客户端进行展示。
后端路由的缺点:
一种情况是整个页面的模块由后端人员来编写和维护的.
另一种情况是前端开发人员如果要开发页面,需要通过PHP和Java等语言来编写页面代码.
而且通常情况下HTML代码和数据以及对应的逻辑会混在一起,编写和维护都是非常糟糕的事情.
1.2.2前后端分离阶段,前端渲染:AJAX
前端渲染就是浏览器请求的数据都是在前端渲染的。
前后端分离时前端开发者只需要关注和用户的交互,后端开发者只需要关注提供API接口。
1.2.3前端路由阶段:SPA页面(单页面富应用)
整个网站只有一个html页面.
实现的基本原理是资源服务器中只有一个html页面一个css文件和一个js文件,当用户发出请求时,会将静态服务器上的全部资源下载下来,当用户访问指定的页面时会选择性地加载相应的页面(html.css.js文件),实现单页面富应用的技术支撑就是前端路由。说白了选择性地显示页面技术的实质就是组件化技术。
前端路由实际上是一种url和资源之间的映射关系,是建立在前后端分离基础之上的。
2、vue-router基本使用
2.1安装vue-router
步骤一:安装vue-router
npm install vue-router --save
步骤二:在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)
第一步:导入路由对象,并且调用Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例
使用脚手架的时候选择安装路由的话就不需要再安装路由了。
2.2搭建路由框架
2.3使用vue-router
2.3.1:创建路由组件
这里的路由组件实际上是功能模块,因为每个请求都对应一个功能组件。
2.3.2:配置路由映射:组件和路径映射关系
path表示url中含有’/home‘或者’/about‘才显示对应的组件。
2.3.3:使用路由:通过<router-link>和<router-view>
2.3.4</router-link>标签的补充
(1)tag属性: tag可以指定<router-link>之后渲染成什么组件,比代码会被渲染成一个<button>元素,而不是<a>
效果
(2)replace属性: replace不会留下history记录,所以指定replace的情况下,后退键返回不能返回到上一个页面中。
(3)active-class属性:当<router-link>对应的路由匹配成功时,会自动给当前元素设置一个router-link-active的class,设置active-class可以修改默认的名称.
≥在进行高亮显示的导航菜单或者底部tabbar时,会使用到该类.
>但是通常不会修改类的属性,会直接使用默认的router-link-active即可.
2.4通过代码的方式修改路径
前面在使用<router-link>标签的时候可以做到点击链接或者是button会显示相应的组件,而且地址栏的路径会相应的改变。但是如果不使用<router-link>标签的话,如何实现上述功能呢?
2.5动态路由
2.5.1动态路由的使用
(1)编写路由组件
(2)配置路由组件和路由之间的关系
(3)使用路由组件
2.5.2动态路由扩展
需求:当点击“我的”时 ,会在该组件中显示路径中的信息。
2.6打包文件的结构
项目执行:npm run build 指令时会将项目打包。打包后生成dist文件如下:
2.7路由懒加载
2.7.1什么叫懒加载?
什么叫懒加载?用到时再加载。
路由懒加载的主要作用就是将路由对应的组件打泡成一个个的js代码块.只有在这个路由被访问到的时候,才加载对应的组件。
2.7.2懒加载的方式
项目打包后:
2.8路由的嵌套使用
比如在home页面中,我们希望通过/home/news和/home/message访问一些内容.一个路径映射一个组件,访问这两个路径也会分别渲染两个组件.
2.8.1实现嵌套路由的步骤
(1)创建 对应的子组件,并在路由映射中配置对应的子路由。
(2)在组件内部使用<router-view/>标签。
3、vue-router参数传递
就是在路由跳转的时候需要参数传递。
3.1传递参数的类型
传递参数主要有两种类型: params和query
3.1.1params类型
配置路由格式: /router/:id
传递的方式:在path后面跟上对应的值
传递后形成的路径: /router/123,/router/abc
使用该方式传递参数,只能传递简单的参数。
3.1.2query的类型
配置路由格式:/router,也就是普通配置
传递的方式:对象中使用query的key作为传递方式
传递后形成的路径:/router?id=123,/router?id=abc
运行:
因为query传递的数据是对象类型,所以适合传递大量的参数。
3.1.3$router和$route的区别
3.2全局导航守卫(前置钩子函数)
学习链接:导航守卫 | Vue Router
所谓的导航守卫实际上是指,在URL来回跳转的时候做监听,以便当前URL跳转到其他URL时可 以做一些其他的操作。
3.2.1三个生命周期函数
create():在创建出组件之后回调该函数
mounted():当template挂载到DOM上的时候回调该函数
update():当页面发生刷新的时候回调该函数
案例:
每次点击对应的URL时,网页上的标题会显示该URL对应的文字。
因为涉及到路由的跳转,因此需要在router下的index.html下写:
在实际开发中可以判断用户是否登录,登录的话跳转到下一个,没有登录的话跳转到next("/");
3.3全局导航守卫的补充
3.3.1全局后置钩子函数(router.afterEach)
在前面小节中使用的是全局前置钩子函数(router.beforeEach)来实现标签跟随URL的改变,但是还有一种就是后置钩子函数()
/*全局后置钩子函数*/ router.afterEach((to, from) => { document.title = to.matched[0].meta.title; })
使用后置全局钩子函数不需要再调用next();方法。
3.3.2其他守卫
(1)路由独享守卫
学习链接:导航守卫 | Vue Router
(2)组件内守卫
学习链接:导航守卫 | Vue Router
4、keep-alive遇见vue-router
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存︰
这样的话在调用组件的之后就不用每次都创建了,也就是说组件在创建完成之后不会自动销毁,可以提升性能。
4.1keep-alive的两个属性
include -字符串或正则表达,只有匹配的组件会被缓存
exclude -字符串或正则表达式,任何匹配的组件都不会被缓存
这样User组件和profile组件在使用时会被创建,当切换到其他的组件的时候会被销毁,如此循环往复。
5、小案例TabBar
(1)在终端使用脚手架创建项目tabbar
PS D:\Vue\vue06-router> vue init webpack tabbar
(2)因为App.vue组件是浏览器DOM的实例,因此首先会想到直接在App.vue组件中定义。
效果:
上面的代码都是写在App.vue文件中的,但是存在代码复用性差的问题,而且缺少图片的问题,因此要将TabBar组件抽取出来。
也就是需要将App.vue中的关于TabBar的组件抽取出来,又因为组件想要在浏览器上显示需要将组件挂载到vue实例,也就是App.vue上因此需要将TabBar.vue导入到App.vue中注册,并在App.vue中使用。
效果还是一样的。
除了有文字还需要加上图标,图标去找阿里的就行:iconfont-阿里巴巴矢量图标库
效果:
但是,根据组件化的思想,TabBar组件只是负责底部的导航栏,而底部的四个图标实际上也是一个的组件,因此我们将放在导航条中的图标封装到1个组件中,在导航条中使用就行了。
根据上图,TabBarItem组件中的内容(也就是图标不是写死的,可以根据我们的需要方便进行相关的修改和添加)是个插槽,TabBar组件中也是插槽,因为图标的数量和内容是可修改的。
TabBar组件内容
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
}
</script>
<style scoped>
/*设置文字排列在一行上,设置TabBar背景颜色为浅灰色,并将TabBar放到下面,设置TabBar顶部的阴影*/
#tab-bar{
display: flex;
background-color: #f6f6f6;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 -1px 1px ,rgba(100,100,100,.2);
}
</style>
TabBarItem组件内容:
<template>
<div class="tab-bar-item">
<!-- 具名插槽 -->
<slot name="item-icon"></slot>
<slot name="item-txt"></slot>
</div>
</template>
<script>
export default {
name: "TabBarItem"
}
</script>
<style scoped>
.tab-bar-item{
flex: 1;
text-align: center;
height: 49px;
}
.tab-bar-item img{
width: 24px;
height: 24px;
}
</style>
App组件内容:
<template>
<div id="app">
<!-- 3、使用组件TabBar和TabBarItem组件-->
<tab-bar>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/首页.svg" alt="">
<div slot="item-txt">首页</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/分类.svg" alt="">
<div slot="item-txt">分类</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/购物车.svg" alt="">
<div slot="item-txt">购物车</div>
</tab-bar-item>
<tab-bar-item>
<img slot="item-icon" src="./assets/img/tabbar/我的.svg" alt="">
<div slot="item-txt">我的</div>
</tab-bar-item>
</tab-bar>
</div>
</template>
<script>
/*1、导入TabBar组件和TabBarItem组件注册到App.vue实例中并使用*/
import TabBar from "./components/tabbar/TabBar";
/*导入图标组件*/
import TabBarItem from "./components/tabbar/TabBarItem";
export default {
name: 'App',
components: {
/*2、注册*/
TabBar,
TabBarItem
}
}
</script>
<style>
/*引入css样式*/
@import "./assets/css/base.css";
</style>