IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue教程-day07-2018年12月28日笔记 -> 正文阅读

[JavaScript知识库]Vue教程-day07-2018年12月28日笔记

文章目录

2018年12月28日 上午

image-20210911100955736

第107个视频 - vue-router动态路由的使用

需求

image-20210911101706101

image-20210911101841160

image-20210911102118494

image-20210911102202533

然后我们去App.vue当中去设置router-link。

image-20210911102310856

跑动显示的效果:

image-20210911102358803

但是现在并没有在我们的路径后面拼接动态的内容。

动态路由配置

我们需要在vue-router的配置文件当中,修改变成如下的配置:

image-20210911102506477

如果我们只是修改了这个配置,我们再去跑程序的时候,我们发现现在是这样的效果:

组件渲染不出来了,路径也没有拼接上什么玩意?

image-20210911102552252

我们是需要在App.vue当中拼接上一点东西的。

image-20210911102701661

这个时候的效果:

image-20210911102729645

第三点

我们在真实开发当中/user/zhangsan当中的zhangsan肯定是动态获取的。

image-20210911102823587

这个时候,我们怎么在template当中进行路径的拼接呢?

我们是想要把上面的userId动态绑定到我们的router-link标签当中的to属性的。

这个就是需要用到动态属性绑定,就是v-bind。

image-20210911103033020

稍微回顾一下动态属性绑定

image-20210911103145485

怎么动态绑定呢?

image-20210911105249172

这样的效果就是如下的:

image-20210911105324314

我们就可以根据不同的用户,动态决定路径的信息了。

如果商品的id,也是一样的道理。

再提个需求

如下图:

image-20210911105439115

用户界面希望拿到路径当中的userid的信息,就是如图的lisi,在页面上进行展示。

这个情况怎么做呢?

这个时候,需要在我们的User.vue这个组件当中,使用$route这个属性。

一定,一定要注意区分和$router这个属性。

回顾一下$router属性

昨天,我们在使用代码来进行组件路由跳转的时候,我们使用了button,使用了事件监听,在methods方法当中,我们进行代码的路由跳转的时候,我们使用$router属性,使用了它的push方法和replace方法。

image-20210911105748009

这个$router是谁的呢?

这个就是我们的router/index.js当中创建的大的路由对象了。

image-20210911110033747

我们现在要用$route属性

我们现在是为了在我们的组件当中,获取我们url路径当中的动态拼接的部分信息,在我们的组件页面当中进行展示的。

$route是什么意思呢?

r o u t e 就 是 表 示 , 当 前 哪 个 路 由 处 于 活 跃 状 态 , 这 个 route就是表示,当前哪个路由处于活跃状态,这个 routeroute表示的就是哪个路由组件。

r o u t e r 是 我 们 在 r o u t e r / i n d e x . j s 当 中 创 建 的 r o u t e r 对 象 , 就 是 路 由 对 象 。 这 个 路 由 对 象 当 中 有 好 几 个 路 由 。 哪 个 路 由 处 于 活 跃 状 态 , router是我们在router/index.js当中创建的router对象,就是路由对象。这个路由对象当中有好几个路由。哪个路由处于活跃状态, routerrouter/index.jsrouterroute就是表示哪个路由组件。

image-20210911110434732

image-20210911110650515

我们就是通过上面的过程,在路由组件当中,通过$route.param方法来拿到了动态拼接的路径参数。

image-20210911110716393

直接获取展示

我们也可以直接在User.vue当中,直接获取展示:

image-20210911111151817

总结

第一,我们在router/index.js,路由配置文件当中,配置了动态拼接的路径参数。

第二,我们在App.vue当中,data属性当中表示获取的动态数据userid,然后通过动态绑定,给router-link的to属性动态绑定了userid路径。

到这里,我们就能够实现在路径后面动态拼接路径了。

第三,我们在User.vue当中,通过$route这个参数,获取到params,获取到路由配置文件当中拼接的路径参数,在页面当中进行展示。

所以,关键就是index.js当中的动态路由配置。

ppt

image-20210911111356356

第108个视频 - vue-router - 路由懒加载的使用

认识路由的懒加载

image-20210911111434989

之前我们自己配置过webpack。

我们打包的时候,除了img,index.html,其他全部都放到了bundle.js当中了。

这个bundle.js当中会变得非常大。

如果我们从静态资源服务器请求静态资源的时候,可能花的时间非常长,这样用户的浏览器会出现短暂的空白。

这种体验是非常不好的。

脚手架的webpack配置

脚手架当中自动的webpack配置,就是注意到了这个问题,它会对我们的js文件进行分包,而且对我们的css文件也进行了分包。

我们可以验证一下。

我们可以进行一个打包。

image-20210911111804843

我们通过npm run build来进行打包。

image-20210911111905811

我们可以看到css文件是被单独分离出来了,我们之前都是在bundle.js当中的。

抽离打包之后,在index.html当中是对css进行了引用的。

image-20210911112005826

image-20210911112037481

我们可以看到,js文件,也不是打包到一个文件当中的,我们这个项目当中,就是有3个文件的。

第一个文件,叫做app,是application,是当前应用程序开发的所有的代码,只要是你写的业务代码,都在这个js文件当中的。

第二个文件,叫做vendor,这个单词是提供商,第三方的意思,在项目当中你引入了第三方的东西,比如说vue,比如说vue-router,比如axios,比如说betterscroll,这些都是协助我们开发的。这些第三方的东西,webpack打包的时候,全部会打包到vendor.js当中。

第三个文件,叫做manifrest,这个文件是为我们打包的代码,做底层支撑的。我们在项目开发当中,用了很多模块化,用了很多的import,export,在项目当中你既可以用es6的模块化,也可以用commonjs当中的模块化,但是最终打包的js当中可能是不支持commonjs或者es6都不支持。打包出来的js当中,需要通过某些方式,对之前的导入导出,让它有效,让浏览器支持。需要写一些代码。就是manifrest。

image-20210911112653578

我们现在打开manifrest是看不懂里面的代码的,因为已经丑化过了。

我们需要看一下里面的代码,就是不要让它打包的时候丑化。

丑化肯定是在webpack.prod.conf.js当中使用了丑化的插件,就是下面的这个插件:

image-20210911112830662

我们把丑化的插件关掉,然后继续打包,然后打开manifrest.js文件。

image-20210911112912319

我们在业务代码当中使用了导入导出,但是我们在打包的文件当中,是没有原来方式的导入导出的。

看看之前的代码

我们可以看看之前的,我们自己写的webpack的配置打包后的文件。

打包出来的bunlde.js里面的结构是什么呢?

(function (modules){})([]),整个打包出来的bunlde.js当中,就是一个匿名闭包。

这个[]当中,就是我们业务代码当中的一个一个的模块,传入进去了。

image-20210911113729564

然后在(function (modules) {})([])当中定义了一个最最重要的函数,就是下面的函数__webpack_require__

image-20210911113847245

在定义这个__webpack_require__这个函数的同时,还赋予了很多的参数,如上图。

这个__webpack_require__函数有个最最关键的操作:

image-20210911114247877

上面这行代码的意思就是:把__webpack_require__.s赋值为0,然后传入到__webpack_require__函数当中。

在我们打包后的bundle.js当中,我们的模块之间还可以继续引用的原因,就是因为,我们的有__webpack_require__这种代码在支撑。

回到脚手架2打包的代码当中

我们的脚手架2打包出来的第三个manifrest.js当中也是跟上面一样的道理。

在这个js文件当中,也有__webpack_require__这个关键的函数:

image-20210911114622251

这个函数最大的作用,就是模块化的代码进行底层支撑。

之前我们自己打包的时候,我们的业务代码贺支撑代码都是放到了bundle.js当中。

现在脚手架当中的webpack打包的时候进行了代码分离,都放到了manifrest.js当中。

总结

  • app.js:我们的业务代码,application
  • manifrest:支撑代码,运行时支撑代码
  • vendor:第三方代码,例如vue,vue-router。

第109个视频 - vue-router 路由懒加载的使用

解释什么是懒加载

当我们在公司开发一个大型项目的时候,

项目里面的代码,打包之后,app.js当中的代码,会远远大于vendor或者manifrest当中的代码。

当我们的项目部署之后,用户第一次从静态服务器当中进行请求的时候。

vendor和manifrest都会先请求过去的。但是app.js太大了,咋办呢?

我们需要像个办法来对app.js来进行分离。

现在默认情况下,我们所有的业务都是打包到app.js当中的。

在开发当中,我们常规的做法,就是一个路由,打包一个js文件。

而且在用户第一次请求的时候,这个路由的js文件是不会跟着vendor或者manifrest一起给用户的。

之后根据用户的点击,用到了哪个组件,再加载对应的路由组件的js。

懒加载是什么意思:用到的时候再加载

image-20210911115735492


路由懒加载的效果

image-20210911115820759

怎么写懒加载的代码

image-20210911120037953

第一种方式,就是异步组件的写法,能够认识就可以了,不推荐专门记忆这种写法。

第二种方式,是AMD的写法,代码量很少。

第三种方式,就是ES6的写法, 上课会使用的写法。

直接写一个箭头函数,里面跟上一个import,到时候就会动态加载了。

image-20210911120302704

通过这种方式,这样写,就可以了。

当然,也可以这样直接写:

image-20210911120358503

我们推荐大家使用第一种写法。

重新打包程序进行验证

image-20210911120554455

打包完成了时候,三个组件用到了懒加载,打包出来的文件当中就多个三个文件。


第110个视频 - 路由的嵌套使用

场景

我们希望在首页/home当中,配置一些其他的东西。比如/home/news,比如/home/message。

这个场景,就是路由的嵌套。

认识路由的嵌套

image-20210911120744817

路由嵌套第一步 - 创建子组件

image-20210911121114456

注意:ul>li{消息$}*4记住这种webstorm的小技巧的写法。

如上面的图,我们创建了连个子组件:HomeMessage,HomeNews表示这个就是首页的子组件。

路由嵌套第二步 - 路由映射中配置子路由

将我们的子组件懒加载进来:

image-20210911121650348

然后配置子路由:

image-20210911122421870

路由嵌套 - 设置子组件页面占位

设置router-view

image-20210911121912277

设置router-link

image-20210911122810871

注意,这里的router-link当中的to属性当中的路径,是需要写一个完整的路径的,就是/home/news,不能够直接写/news,不能够写home/news,这个home/news是王红元在讲课的时候,疏忽的犯错的一个地方。

效果

image-20210911122213597

然后我们点击新闻,下面的东西就显示出来了。

image-20210911122308891

小问题1

如下图所示:

image-20210911123041423

第一次,用户进入了首页,点击了新闻。

第二次,用户点击了用户标签,进入了用户界面。

第三次,用户点击了首页,回到了首页界面,但是新闻那个内容,就不显示了。

这个从交互逻辑上来说,肯定是不好的。

小问题2

image-20210911123208622

用户第一次进来,首页里面新闻和消息的位置什么都没有显示。

默认情况下,应该显示新闻或者消息的。

所以应该有一个默认的路径的。

问题1和问题2 - 配置子组件的默认路径

image-20210911123317540

效果就是用户访问:localhost:8080的时候,默认的路径就是如下图所示:

image-20210911123351828

问题3

第一,我在首页当中,点击了消息,显示了首页当中消息的内容。

第二,我跑了,我点击了关于页面。

第三,我又回来了,我们添加了子组件的默认路径的时候,回到首页看到的是新闻的内容,但是我还是想要看到第一步当中的消息的内容。

这个怎么做呢?

这个我们放到后面讲解。

这个用一个pipeline就可以了。

第111个视频 - vue-router参数传递(一)

场景

当我们从一个路由组件,跳转到另外的一个路由组件的时候,我们希望能够传递一些消息的。

一开始我们显示的肯定是App.vue这个页面的。

因为我们配置了默认路径,所以在App.vue当中还显示了首页了。

我们从App.vue当中,点击了【用户】按钮的时候,页面就会跳转到【用户】页面了,就是User.vue组件了。

我们希望给【用户】这个界面传入一些东西。

前面我们传递参数的方式

之前我们点击了用户按钮,通过动态路由的方式,动态绑定了router-link的to属性。

然后我们在用户组件当中通过$route.param获取到了路径当中的动态参数。

这就是一种方式。

image-20210911124555708

看看ppt

image-20210911124247150

在很多的项目当中,我的用户的界面,一般都叫做Profile,不要起名叫做me或者my。

  • Profile可以翻译成为档案。

传递参数的方式

image-20210911124656344

验证query类型

第一步:创建Profile组件

image-20210911124849243

第二步,在router/index.js当中懒加载导入组件

image-20210911124921204

第三步,在index.js当中的,路由对象的,route属性对象当中配置路径和组件的映射关系:

image-20210911125002572

第四步:配置页面中的router-link标签

image-20210911125047250

效果:

image-20210911125109042

需求:跳到档案的时候,想要传递一些参数,名字,身高,年龄,等等。

怎么使用query传递参数呢?

第一,如果想要传递参数的时候,router-link的to属性的值,不能是个字符串了,必须是个对象。

第二,这个对象动态绑定到我们的to属性上。

第三,在对象当中,我们可以配置很多的属性,比如说path属性。

我们写的效果是这样的:

image-20210911125454657

我们这种to属性的写法,跟以前是一样的,也是可以实现跳转的,如下图所示:

image-20210911125549649

我们使用对象写法的时候,就可以加上其他的属性了。

image-20210911125640410

我们如果是上面的写法的话,验证的效果,就是下面的效果:

image-20210911125750651

拓展:url的完整写法

image-20210911130230650

image-20210911130318994

image-20210911130338523

image-20210911130505002

image-20210911130615833

这个userinfo,在git当中会用到,在网站的url当中很少用到。

如果你做过gpu开发的话,gpu当中就有这个fragment。

之前我们的params属于path后面的参数。

注意从url的结构,区分params和query和path。

在组件当中获取query参数

image-20210911130944511

得到的效果如下所示:

image-20210911131003706


第112个视频 - vue-router参数传递二

场景

image-20210911131120997

我们可以看看上面的代码。

  • 用户那里,我们是通过动态绑定了router-link的to属性,然后直接在路径后面拼接了params参数userId传过去了,然后路由组件可以通过$route.params来获取。
  • 档案那里,我们是通过动态绑定了router-link的to属性,然后绑定了一个对象,对象当中设置了path和query,然后路由组件可以通过$route.query来获取。

如果我们不使用router-link,我们使用的是button呢?

我们点击button的时候,我们通过代码实现的方式,跳转到对应的组件,然后我们传递过去一些参数。

回忆之前

我们之前,通过代码实现路由组件跳转的时候,是通过button绑定了点击事件,然后在事件方法当中是通过$router对象的push或者replace方法来实现了路由组件的跳转的。

image-20210911131640664

代码实现路由跳转和query传参

image-20210911232255829

效果如下:

image-20210911131933176

第113个视频 - r o u t e r 和 router和 routerroute的由来

胡天伟的预习

$router是我们在通过代码来实现组件跳转的时候,没有使用router-link的时候,用到的对象。

$route代表的是在激活的组件当中获取params或者query参数的时候,使用的。

ppt

image-20210911132221992

解释的准备工作

第一,我们在一个组件当中,就是User.vue当中,新增一个按钮,希望点击这个按钮的时候,就打印一下$router这个对象。

image-20210911132407929

第二,我们在项目的入口文件,也就是main.js当中打印一下路由对象:

image-20210911132503233

这个router就是我们导入的,是我们从router/index.js当中导出,就是如下图所示的:

image-20210911132539328

这个导出的router,就是我们使用vue-router插件,创建的路由对象。

我们的目的是:对比一下组件当中打印的$router对象,是不是,和我们在router/index.js当中根据vue-router插件创建的路由对象是一回事呢?

image-20210911134250357

我们可以看到router对象完全一样。

也就是说$router就是我们在router/index.js当中使用vue-router插件创建的路由对象。

看看源码

image-20210911134437371

我们可以看到VueRouter这个类当中有各种方法,有push,replace,go,back,forward这些方法。

任何一个组件当中,通过this.$router拿到的对象都是一样。

this.$route

先打印看一下:

image-20210911134705198

image-20210911134731006

这个打印的$route对象是什么呢?

就是我们在router/index.js当中配置的动态路由:

image-20210911134817329

因为这个路由当前处于活跃的,所以$route就是这个路由。

$route拿到的就是处于活跃的路由。


另外的角度解释 r o u t e r 和 router和 routerroute

必须看源码

image-20210911135057444

image-20210911135106855

看一下项目当中使用的vue-router的真实的版本是:

image-20210911135202143

然后从github上面下载这个vue-router的源码。

发散:Vue当中使用插件

之前我们讲过,当我们使用vue-router的时候,第一步,就是使用Vue.use(VueRouter)

image-20210911135352549

任何插件的使用都是这样的。比如说我们后来使用vuex的时候,也是这样的。

我们第一步都是要使用use方法来进行安装插件的。

如果我们执行了上面的代码的时候,在插件内部会去vue-router的install方法的。

看vue-router的源码

image-20210911135608366

  • 看源码,推荐从package.json开始看。
  • 先看package.json当中的scripts。
  • 直接读src。

我们看这个源码,就是要看看VueRouter对象的install方法。

源码当中index.js当中VueRouter对象当中,一开始install当中是void的。

image-20210911135806118

到index.js最后的时候,又给VueRouter.install复制了新的值:

image-20210911135906550

我们点击去install,来到了install.js当中。

在install.js当中的第一个东西

image-20210911140042302

为什么我们的代码当中能够使用router-link标签和router-view标签呢?

因为看到上面的代码当中,使用了Vue.component注册了两个全局组件。

为什么在源码当中注册的组件是RouterView,我们使用的时候,使用的是router-view标签呢?

这是一个约定俗称的玩意。

举个例子:

image-20210911140249018

我们自定义组件的时候,名字都是这种驼峰的方式的。但是我们在页面当中使用组件的时候,标签我们都是采用小写的方式的。

为什么组件当中有 r o u t e r 和 router和 routerroute属性呢?

我们先看看下面的图:

image-20210911140439270

为什么我们的自定义组件当中,都会有 r o u t e r 和 router和 routerroute属性呢?

我们先说一个结论:所有的组件都继承自Vue类的原型prototype

上面的图中,User.vue这个组件,是一个对象的,都是继承自Vue类的原型的。

想要真正理解这句话的话,就必须去看Vue的源码。

知道这句话有什么用呢?

理解Vue原型的测试

第一,我们给vue的原型增加了一个test方法。

image-20210911140822821

第二,我们在User组件当中,使用test方法。

image-20210911140918302

举例:

image-20210911141134699

效果:

image-20210911141152265

所以,VueRouter就是给Vue的原型上面,增加了 r o u t e r 属 性 和 router属性和 routerroute属性。

在install.js当中看的第二个东西

image-20210911141403185

这里使用了一个Object.defineProperty的方法,给Vue.prototype上面增加了 r o u t e r 和 router和 routerroute属性。

解释一下Object.defineProperty

我们可以通过Object.defineProperty(对象,属性的key,属性的value)这个方法,给一个对象添加属性。

image-20210911141600397

这个方法,是Vue响应式实现的核心。


第114个视频 - 全局导航守卫

ppt

image-20210911142517845

场景说明

image-20210911142600813

我们希望对来回跳转的这个过程,做一点监听,可以在对应的监听函数当中做你想做的事情。

导航守卫最主要就是监听,你从哪里跳到了哪里。这种作用的。

需求

image-20210911142728899

在我们当前的项目当中,我们的浏览器页签上面的标题是固定的。

这是因为在我们的项目当中,index.html当中title是固定的。

image-20210911142812980

我的需求是,我点击首页的时候,标题就显示首页。

我点击关于的时候,标题就显示关于。

就是这个需求。

你会不会做这个需求呢?

之前的方案

之前我们讲过生命周期的。

任何的vue实例和我们的组件都是有生命周期的。

有个生命周期函数叫做created(),这是我们的组件被创建的时候,会回调的生命周期函数。

还有一个生命周期函数叫做mounted()。当我们将我们的template挂载到整个dom上面的时候,会回调的函数。

并不是说你的组件一创建出来,就会挂载到dom上面的。

顺序是先创建组件,然后再讲.vue文件当中template挂载到dom上面的。

还有一个生命周期函数叫做updated()。这个是在我们的界面发生更新的时候,会回调的函数。

比如说,我们当前界面当中有一个mustache语法绑定的数据,数据改变了,响应式的,界面会发生更新的,这时候,就会回调update()函数。

这三个生命周期函数是最常用的。


我们现在导航上有四个标签:首页,关于,用户,档案。

第一步:如果我们的home、about、user、profile全部都实现一下created()生命周期函数。

第二步:验证,我们跑起来项目,然后点击哪个导航标签,就打印cteated()函数当中的内容。

image-20210911143553887

所以为了实现上面的需求,我们可以直接在每个组件的created()函数当中来改变title。如图所示的代码:

image-20210911143659997

效果是如下图:

image-20210911143748050

这个实现方案有个致命确定:一个功能的实现,涉及所有的组件,真是要命。

现在的方案 - 全局导航守卫

我们可以在router/index.js当中设置全局导航守卫。

第一步:使用vue-router插件创建的VueRouter路由对象,调用它的beaforEach方法。

image-20210911144034411

第二:这个beforeEach方法,看源码是要求传入一个NavigationGuard。

这个NavigationGuard是个什么玩意呢?

我们点进去看一看,看到下面的内容:

image-20210911144217891

我们可以看到,这里的代码就是定义了一个NavigationGuard的类型,这个定义类型就是相当于起别名,就是相当于给后面的箭头函数起了别名。

也就是说这个NavigationGuard就是一个函数。

image-20210911144651179

也就是说,我们调用路由对象的beforeEach方法的时候,要传入一个函数。

vuerouter.beforEach(NavigationGuard)这个意思就是,传入一个函数。这个函数有三个参数,就是to,from,next。

也就是说:vuerouter.beforEach((to, from, next) => {} )

一个结论

我们在beforEach方法当中必须调用next(),也就是如下图:

image-20210911144951915

如果我们这里不调用next()的话,路由跳转就失效了。

现在的方案 - 全局导航守卫

第一,我们可以在index.js当中的routes对象中,给每一个route对象,都加上一个meta属性,在meta当中设置title。

image-20210911145349628

第二,我们利用全局导航守卫来实现上面的需求。

image-20210911145502441

需要注意的是router这个东西,是我们创建的路由对象。

router对象当中,有一个beforeEach方法。

这个方法的参数,是需要传入一个全局导航守卫,也就是NavigationGuard。

这个NavigationGuard就是全局导航守卫。它的本质是一个函数。

这个函数有三个参数,to,from,next。其中to和from都是route对象,也就是routes当中配置的组件路径关系对象。

next也是一个函数,必须调用next()才能够跳转正常。

效果

image-20210911145757924

路由嵌套的小问题

image-20210911145910227

上面的图当中,我们打印了一下导航守卫当中的to对象,因为有路由嵌套,所以,我们可以看到to对象当中的meta当中没有title属性,

所以,上面的title显示的是undefined。

我们 matched属性当中去寻找:

image-20210911150030027

完善需求实现的代码

image-20210911150123306

  • 有路由嵌套的时候,从to对象的matched当中拿到第一个数组元素的meta,获取meta当中的title。
  • 没有路由嵌套的时候,通过上面的方式,也能够拿到meta当中的title。

第115个视频 - 导航守卫的补充

ppt

image-20210911150351229

image-20210911150409349

元数据

元数据,就是描述数据的数据。很多语言当中都有一个metaclass,就是元类,元类创造类对象,类对象创造实例对象。

前置钩子和后置钩子

导航守卫,就是当发生路由跳转的时候,执行的一些函数。

我们可以看到vue-router的源码当中,有这些函数beforeEach和afterEach这些函数

image-20210911150832325

beforeEach就是叫做前置守卫,afterEach就是叫做后置钩子。

beforeEach就是路由跳转开始之前,会回调的函数,必须执行next()。

afterEach就是路由跳转完成之后,会回调的函数,不需要执行next()。

验证

image-20210911151359174

我们可以看到跳转的内容:

image-20210911151502161

全局守卫

我们之前写的beforeEach和afterEach,这些都是全局守卫。

我们还有路由独享守卫。只有我们进入到某个路由里面的话,才会回调的函数。

我们就想要观察一下,什么时候进入到我们的about路由当中,调用一个回调函数。

我们可以在官方网站来进行一个学习。

我们简单读一下就可以了。

next()的多种用法

用户已经登录过了,我们可能就是直接用next(),正常跳转到下面的就可以了。

用户如果没有登录的情况下,我们就可以使用next('/login')的其他跳转方式。

image-20210911151909012

路由独享守卫

image-20210911152015710

image-20210911152229759

组件内的守卫

image-20210911152327519

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave

根据不同的业务需求,来到开发文档当中,查询:全局导航守卫,路由独享守卫,组件内的守卫。


第116个视频 - vue-router-keep-alive及其他问题

ppt

image-20210911152618068

场景

之前我们说过一个业务场景,会放在后面解决,我们回顾一下。

第一,用户第一次进来,是这个页面。

image-20210911152818488

第二,用户在首页当中点击了消息。

image-20210911152839142

第三,用户点击了用户这个页面

image-20210911152855775

第四,用户又回到了首页

image-20210911152910653

在这个时候,用户回来到首页的时候,看到的是新闻,而不是之前看到的消息,如果想要看到消息,还必须自己手动点击一下消息才可以。

这个不是非常人性化的。

场景解释

这个场景的意思就是说,我们组件内部的所有的状态,是没有被保留下来的。

每次用户在路由组件之间进行切换的时候,比如说从用户组件到首页组件的时候。

会重新创建一个新的首页组件的。

如果我们希望把组件状态给保留下来,不想要重新创建新的组件的时候。

这个时候,我们就可以使用keep-alive了。

keep-alive理解

router-view是一个组件,如果我们现在把router-view放在keep-alive组件当中,所有路径匹配到的视图组件到时候就会被缓存。

也就是说,keep-alive可以简单理解成为一个缓存标识。

keep-alive是vue内置的组件。

router-view是vue-router内置的组件。

演示

new Vue或者创建一个组件的时候,都会有很多生命周期函数。

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. beforeDestory
  8. destoryed

演示

image-20210911154205817

我们给我们的home组件,设置了两个生命周期函数,然后我们通过在路由切换的时候,看看这个组件是否是,会被频繁创建和频繁销毁的。

image-20210911154420411

我们希望他们每次都创建一个新的吗?

肯定是不希望的。

我们可以这样做:

image-20210911154549647

这样组件就不会频繁创建了。性能就提升了。


场景需求实现的第一种方案 - 这种方案不行

第一步:取消我们原来在路由映射关系配置当中的,首页子组件重定向

image-20210911154956704

第二步:结合keep-alive,我们在created生命周期函数当中,使用$router对象,就可以改变路径

image-20210911155016343

但是这种方案还是不行。

场景需求实现的第二种方案 - 这种方案不行

image-20210911155320327

当页面是活跃状态的时候,执行activated()函数。如果是页面不活跃的情况下,执行deactivated()函数。

image-20210911155631065

上面这张图当中的分析,是错误的。在页面已经不活跃的时候,this.$route.path,记录的是活跃的组件的path。

所以,这个方案也不会达到效果的。

场景需求实现的第三种方案 - 组件内守卫

image-20210911161255845

activated是为了在页面活跃的时候,给一个默认的路径。

在beforeRouteLeave,就是用户跳转离开之前,我们记录一下用户最后的路径。保存下来。

效果:

image-20210911160418172

activated函数和deactivated函数

image-20210911161510109

activated函数是当页面处于活跃状态时候,回调的函数。

deactivated函数是当页面处于不活跃状态的时候,回调的函数。

之所以,activated和deactivated函数能够执行,这是因为在App.vue当中router-view放在了keep-alive当中。

如果像是下面图片所示的那样,没有keep-avlie了,那么这两个函数也就不会执行了。

image-20210911232158376

本节课讲的内容

image-20210911162141771

第117个视频 - keep-alive属性介绍

需求场景说明

image-20210911162512171

现在我们通过在App.vue当中,给router-view标签包裹了keep-alive,所以上面图中的首页,关于,用户,档案四个组件都不会频繁创建和销毁了。但是我们的需求是:

我不管首页,关于,用户,我要档案这个组件每一次点击进来的时候,都要重新创建。

怎么实现。

keep-alive的属性

include属性和exclude属性

上面的需求,我们通过下面的代码,就可以实现了。

image-20210911162855271

如果是有两个组件想要exclude的时候,我们使用下面的写法,就看可以了:

image-20210911163015768

这里要注意:这里不要随便加空格。

正则表达式当中也不要随便加空格。

image-20210911163247319

第118个视频 - tabbar基本结构的搭建。

ppt

image-20210911163454197

需求场景描述

给我封装一个tabbar组件,让我可以自定义传入图片和文字,然后就能够直接用。

分析思路

第一,我们需要把tabbar封装成为独立的组件,希望不仅仅在这个项目当中能够用,下个项目当中也能够用的。下个项目当中,传入对应的文字和图片就可以根据项目需求生成对应的tabbar。

第二,tabbar的item的图标的个数也是不一定。文字,图片都不是定义死的。

首先,我们的大横框框,是一个组件,我们叫做TabBar,这个组件当中定义插槽,slot。让外界决定给我们这里传入几个插槽。

然后,我再封装TabBarItem这样的小组件,如果你的插槽当中准备放置四个东西的话,你可以创建四个TabBarItem给我的插槽替换掉的。

我通过flex布局,自动把这几个item布局好。

我分成了两类组件,大的叫做TabBar,小的组件叫做TabBarItem,在Item组件当中,图片和文字都是slot。

创建项目

第1个问题 - 显示的字体没有挨着屏幕边缘

image-20210911165138772

这是因为body默认是有margin和padding这些东西的。

在开发当中,针对这种东西,我们一般会怎么做呢?

  • assets当中一般都是放置资源,我们创建两个文件夹,img文件夹,放图片,css文件夹,放置css文件。
  • css文件夹当中创建base.css文件,进行如下的设置。

image-20210911165411041

设置完了之后,我们在main.js文件当中引用一下这个css文件。

这样这个css文件才会生效的。

image-20210911165522600

但是我们的main.js当中尽量不要写上面的require的代码。

这个时候得到的效果是:

image-20210911165632712

第2个问题:我们尽量不要再main.js当中写require css这种代码

我们应该在App.vue的style当中写。

image-20210911165821146

效果是:

image-20210911165841912

第3个问题:要初始化的样式非常多,所有初始化样式都写到App.vue不合适

我们在App.vue的style当中动态引用文件的。

就是如图这样写:

image-20210911170030985

效果还是一样的:

image-20210911170057711

第4个问题: 四个item没有水平分布

我们应该使用flex进行布局

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
};
</script>

<style>
@import "./assets/css/base.css";

#tab-bar {
  display: flex;
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
}
</style>

得到的效果,就是如下图所示:

image-20210911170412108

第5个问题:所有的文字都是靠左边的

增加text-align,设置为center。

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
};
</script>

<style>
@import "./assets/css/base.css";

#tab-bar {
  display: flex;
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
}
</style>

效果是:

image-20210911170503287

第6个问题 - 当前item的高度很矮

如图所示:

image-20210911170615567

一般我们的tabbar的高度是49px,在移动端

像是ios或者android当中,都是49px的。

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
};
</script>

<style>
@import "./assets/css/base.css";

#tab-bar {
  display: flex;
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
}
</style>

效果:

image-20210911170800377

第7个问题 - 现在tabbar的背景颜色和页面的背景重合

为了好看,要给tabbar一个颜色。

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
};
</script>

<style>
@import "./assets/css/base.css";

#tab-bar {
  display: flex;
  background-color: #f5f4f5;
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
}
</style>

效果:

image-20210911171052133

第8个问题 - tabbar在页面上边希望在下面

为了让tabbar跑到页面的下面,我们使用下面的样式代码:

image-20210911171319473

效果:

image-20210911171341014

第9个问题 - tabbar和页面的结合处有阴影

我们可以看看效果图:

image-20210911171524266

就是图中的位置,在tabbar和页面主体之间有一点点阴影,这样看起来会比较平滑,不会很突兀。

所以在这里添加一点阴影。

我们要使用box-shadow属性了。

box-shadow有四个参数。

第一个参数是x轴。

第二个参数是y轴。

第三个参数是模糊程度。

第四个参数是颜色,颜色可以使用rgba,这样我们可以设置透明度。

阴影移动的原理

如图所示:

image-20210911171907420

如上图所示,如果x为正的话,阴影是往右边走的。如果y为正的话,阴影是往下边走的。

我们现在是希望阴影往正上方走的,所以x应该为0,y应该是个负数。

代码:

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
};
</script>

<style>
@import "./assets/css/base.css";

#tab-bar {
  display: flex;
  background-color: #f6f6f6;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: 0 -1px 1px rgba(100, 100, 100, .15);
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
}
</style>

效果:

image-20210911172531323

第119个视频 - TabBar和TabBarItem组件封装

第1个问题 - 现在没有复用性

image-20210911172709237

我们在components文件夹下,新建一个tabbar文件夹。

这是因为,后面我们要在components下面放上很多的封装的组件。

所以说,为了方便管理,我们新建一个tabbar的文件夹。

然后在tabbar的文件夹下面我们创建一个TabBar.vue这个组件。

然后我们将原来在App.vue当中的代码,抽离到TabBar.vue当中。

App.vue当中的代码:

<template>
  <div id="app">
    <tab-bar>
      
    </tab-bar>
  </div>
</template>

<script>
import TabBar from "./components/tabbar/TabBar";

export default {
  name: 'App',
  components: {
    TabBar
  }
};
</script>

<style>
@import "./assets/css/base.css";
</style>

TabBar.vue

<template>
  <div id="tab-bar">
    <div class="tab-bar-item">首页</div>
    <div class="tab-bar-item">分类</div>
    <div class="tab-bar-item">购物车</div>
    <div class="tab-bar-item">我的</div>
  </div>
</template>

<script>
export default {
  name: "TabBar"
};
</script>

<style scoped>
#tab-bar {
  display: flex;
  background-color: #f6f6f6;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: 0 -1px 1px rgba(100, 100, 100, .15);
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
}
</style>

现在的效果不变。

第2个问题 - tabbar当中显示的是文字和图片,不仅仅是文字

我们准备一些图片文件:

image-20210911173455555

第3个问题 - 图片怎么用?

我们需要在TabBar.vue当中引用图片。

image-20210911182241375

但是我们引入图片的时候,我们发现这种路径,真的是太恶心了,这种路径太长了。

这个问题后面再说。

写一个锚点记录一下。

问题锚点

第4个问题 - 图片展示效果太大了。

现在我们在tabbar.vue当中引入了四张图片。

代码如下:

<template>
  <div id="tab-bar">
    <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/home.svg" alt="">
      首页
    </div>
    <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/category.svg" alt="">
      分类
    </div>
    <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/cart.svg" alt="">
      购物车
    </div>
    <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/profile.svg" alt="">
      我的
    </div>
  </div>
</template>

<script>
export default {
  name: "TabBar"
};
</script>

<style scoped>
#tab-bar {
  display: flex;
  background-color: #f6f6f6;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: 0 -1px 1px rgba(100, 100, 100, .15);
}

.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
}
</style>

得到的效果是:

image-20210911182737702

这种图片的效果太大了。

所以这个时候,我要设置一下图片的大小。

通过下面的代码进行设置:

image-20210911183011130

这样得到的效果如下所示:

image-20210911183036690

第5个问题 - 图片和文字在一行显示

这个问题,主要是因为我们的img标签是一个行内元素,我们的文字也是一个行内元素。

我们应该把文字变成块级元素。我们使用div标签来包括一下文字。

image-20210911183222580

这样得到一个效果,如下所示:

image-20210911183244354

第6个问题 - 感觉现在tabbar.vue当中的逻辑很乱

tabbar.vue当中,不仅仅有关于tabbar的东西,还有item东西,不仅仅有item标签相关的东西,还有布局的css相关的东西。

全部都放在了tabbar.vue当中。

我发现这种逻辑是很乱的。

这个tabbar.vue这个组件,应该只关心大横框框的内容。不应该关心item当中文字和图片的这些东西。

所以,我们做下面的两个操作:

第一,我们将tabbar.vue当中template中关于tab-bar-item的部分,全部都放到App.vue当中。暂时的。

image-20210911183701782

第二,我们将TabBar.vue当中关于tab-bar-item的样式也放到App.vue当中。暂时的。

image-20210911183916150

这个时候,我们的TabBar.vue当中的代码逻辑就比较清晰了。

image-20210911184225881

第7个问题 - App.vue当中代码太乱

我们最好是抽离一个TabBarItem这样的组件。

第一步,先将App.vue当中,TabBarItem相关的样式,抽离到我们的TabBarItem.vue当中。

image-20210911185022413

第二步,在我们的App.vue当中,导入TabBarItem组件,然后在template当中使用。

image-20210911185356789

第8个问题 - 我们应该怎么写TabBarItem的template呢?

我们现在先写成这样:

image-20210911185605417

这个时候的效果是:

image-20210911185623338

第9个问题 - 现在我们没有图片

我们在TabBarItem里面,添加图片:

image-20210911200547112

效果如下:

image-20210911200602171

第10个问题 - TabBarItem当中的文字和图片不能写死

既然,我们的TabBarItem当中的文字和图片不能够写死,那我们怎么办呢?

搞插槽就可以了。

吴雁月这样说。

所以,我们修改TabBarItem当中的内容,变成下面的样子:

image-20210911201742900

然后我们在App.vue当中,给插槽,传入对应的值。

image-20210911201858492

第11个问题 - 我们感觉TabBarItem上面的字体有点大

image-20210911202410323

效果:

image-20210911202429338

第12个问题 - 图片距离TabBar上方要留一点空间

我们想在这里留一点空间:

image-20210911202527746

代码:

image-20210911202634259

效果:

image-20210911202606929

第13个问题 - 图片和文字之间的空间有点大

现在,我感觉图片和文字之间的空间有点大。

image-20210911202724827

现在文字和图片两个,是紧挨着的。

为什么会有空间的呢?

因为图片下方会多3px。

我们通过下面的代码去掉:

image-20210911203014017

效果:

image-20210911203002803

现在为啥图片和文字还有一点空间?

这个是图片自己本身就有的空间。

我们可以看看图片本身:

image-20210911203209637

第14个问题 - 图片和文字之间的距离想自定义一下

我感觉上面的图片和文字的空间又稍微有点小了。

我们可以自定义一下子,想要变成2px。

image-20210911203453585

效果如下:

image-20210911203416594

看起来就是好看很多了。

第15个问题 - 重新讨论第10个问题

现在所有的item都是展示相同的文字和图片。

我们想要动态展示文字和图片,让调用方决定。

所以,我们在TabBarItem当中搞两个具名插槽,第一个插槽表示图片,第二个插槽表示文字:

image-20210911203842881

然后我们在App.vue当中的tab-bar-item中,传入我们自己定义的图片和文字,传入具名插槽当中。

image-20210911204651065

我们得到的效果是:

image-20210911204717218

如果我们想要传入五个tab-bar-item,也是可以的。

image-20210911204802779

效果上自动就给我们进行了均等分了:

image-20210911204823264

到这里,我们的基本封装,就已经好了。

到了这一步,以后再其他项目当中,我们要使用tabbar就非常方便。我们什么都不用考虑。

我们只需要在App.vue当中,用tabbar的标签,用tabbar-item的标签,然后传入具体的文字和具体的图片就可以了。

不需要考虑均等分的问题,不需要考虑文字和图片的距离的问题等等。

这就是我们封装的,完全独立的组件。


第120个视频 - 给TabBarItem传入active图片

第1个问题 - 现在只有普通图片,没有活跃状态图片

现在别人给我们传图片的时候,应该传进来两张图片,一张是非活跃的图片,一张是活跃的图片。

这个时候,我们必须在我们的TabBarItem当中,再新增一个插槽的。

我们封装组件的时候,应该这样封装。

让别人把两张图片都传好。

然后我内部动态决定,显示哪一张图片。

这种点击活跃的效果,应该组件自己具备这个能力,不要让开发者决定。

第一步,我们在TabBarItem当中新增一个插槽

image-20210911205706924

第二步,我们在App.vue当中调用tab-bar-item的时候,传入新的插槽。

image-20210911205808721

但是这个时候的效果是这个样子的:

image-20210911205828415

第2个问题 - 怎么能自动展示对应图片?

我们使用v-if和v-else来控制一下。

image-20210911210138272

这样默认情况下,我们的效果是这样的:

image-20210911210325039

如果我们的isActive值变成了true,我们的效果就是这样的:

image-20210911210305415

第3个问题 - 图片活跃的时候,文字应该变成红色

这个时候,我们应该给slot-text来动态绑定属性。

我们应该这样修改TabBarItem当中的代码:

image-20210911210844369

但是我们现在的代码中,isActive是为true的,但是我们得到的效果是如下:

image-20210911210917943

我们看到文字,并没有变红。这是为什么呢?

第4个问题 - 为什么插槽中的文字没有变红?

这是因为插槽slot的本质是,在用户进行slot替换的时候,是会直接复制代码替换slot的代码的。

如下图所示的:

image-20210911211140067

插槽的目的就是要被替换的。我们替换过之后,就不会有isActive这种控制的属性了。

所以,在插槽上动态绑定属性没有什么用的。

第5个问题 - 那怎么动态显示文字呢?

为了解决上面的问题,当需要给插槽动态绑定属性的时候,我们不给slot绑定,我们用div包裹slot,在div上面动态绑定属性。

如下图所示:

image-20210911211600966

这样得到的效果是:

image-20210911211511734

第6个问题 - slot上面的v-if会生效吗?

我们刚才测试,slot上面的v-if是有效的。

但是,slot不是就应该被替换的吗?

image-20210911211933487

这个问题,王红元没有解释,为什么v-if在slot上面是生效的。

但是,为了保险,我们给slot都包裹上一个div,写成下面的样子:

image-20210911212121935

效果跟上面是一样的:

image-20210911212208846

第121个视频 - TabBarItem和路由结合效果

第1个问题 - 当我点击对应item的时候,显示对应的页面

也就是说,我们点击item的时候,和路由跳转结合起来,效果是这样的:

image-20210911212420335

让我们每个item的点击,和大的路由组件,一一对应起来。

所以,我们要手动装一个vue-router。

image-20210911212807014

然后我们在src文件夹下面新建一个router文件夹,然后在router文件夹下面新建一个index.js的配置文件。

import Vue from 'vue'
import VueRouter from "vue-router";

// 1. 安装插件
Vue.use(VueRouter)

// 2. 创建路由对象
const routes = [

]

const router = new VueRouter({
  routes
})

// 3. 导出路由对象
export default router

然后在main.js当中挂载路由:

image-20210911213109338

然后就可以配置映射关系了。

第一,可以先创建四个路由组件了。

针对大的页面,我们一般不会再components目录当中创建组件。

我们会在src当中创建一个views文件夹。有的人也喜欢起名字叫做pages。

在views当中,我们再创建4个文件夹:home,cart,category,profile。

然后在对应的目录下,分别创建Home,Cart,Category,Profile组件。

image-20210911213605685

components文件夹当中,放置的是公共的组件。

页面放置在views文件夹当中,每个页面的子组件都放在对应的各自的文件夹中。

越往上层越抽象,越往下层越具体。

第2个问题 - 配置组件映射关系

import Vue from 'vue';
import VueRouter from "vue-router";

const Home = () => import('../views/home/Home');
const Category = () => import('../views/category/Category');
const Cart = () => import('../views/cart/Cart');
const Profile = () => import('../views/profile/Profile');

// 1. 安装插件
Vue.use(VueRouter);

// 2. 创建路由对象
const routes = [
  {
    path: '',
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home
  },
  {
    path: '/category',
    component: Category
  },
  {
    path: '/cart',
    component: Cart
  },
  {
    path: '/profile',
    component: Profile
  }
];

const router = new VueRouter({
  routes
});

// 3. 导出路由对象
export default router;

第3个问题 - 点击对应item,页面显示对应路由组件

所以要监听整个item的点击。

我们监听item的点击,不是在App.vue当中监听,也就是说,不是在调用组件的地方监听。

我们是要在组件内部监听。

监听item的itemClick点击,然后在methods当中写一个itemClick方法,在方法内通过this.$router.replace()方法来实现路由跳转。

跳转的路径是需要从父组件当中传过来的。不能够是写死的。

所以,我们通过TabBarItem的props接收父组件的link属性,然后通过this.$router.replace(this.link)实现路由跳转。

之后,我们在父组件,也就是App.vue上面每个TabBar中的tab-bar-item标签上,添加link属性。

并且根据vue-router的做法,我们需要在App.vue当中添加router-view来进行占位。

所以,TabBarItem当中的代码如下:

<template>
  <div class="tab-bar-item" @click="itemClick">
    <div v-if="!isActive"><slot name="item-icon"></slot></div>
    <dii v-else><slot name="item-icon-active"></slot></dii>
    <div :class="{active: isActive}"><slot name="item-text"></slot></div>
  </div>
</template>

<script>
export default {
  name: "TabBarItem",
  props: {
    link: String
  },
  data() {
    return {
      isActive: true
    };
  },
  methods: {
    itemClick(){
      this.$router.replace(this.link)
    }
  }
};
</script>

<style scoped>
.tab-bar-item {
  flex: 1; /* 会对多个item进行均等分*/
  text-align: center;
  height: 49px;
  font-size: 14px;
}

.tab-bar-item img {
  width: 24px;
  height: 24px;
  margin-top: 3px;
  vertical-align: middle;
  margin-bottom: 2px;
}

.active {
  color: #ff5777;
}
</style>

在App.vue当中的代码,如下:

<template>
  <div id="app">
    <router-view></router-view>
    <tab-bar>
      <tab-bar-item link="/home">
        <img slot="item-icon" src="./assets/img/tabbar/home.svg" alt="">
        <img slot="item-icon-active" src="./assets/img/tabbar/home_active.svg" alt="">
        <div slot="item-text">首页</div>
      </tab-bar-item>
      <tab-bar-item link="/category">
        <img slot="item-icon" src="./assets/img/tabbar/category.svg" alt="">
        <img slot="item-icon-active" src="./assets/img/tabbar/cart_active.svg" alt="">
        <div slot="item-text">分类</div>
      </tab-bar-item>
      <tab-bar-item link="/cart">
        <img slot="item-icon" src="./assets/img/tabbar/cart.svg" alt="">
        <img slot="item-icon-active" src="./assets/img/tabbar/cart_active.svg" alt="">
        <div slot="item-text">购物车</div>
      </tab-bar-item>
      <tab-bar-item link="/profile">
        <img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="">
        <img slot="item-icon-active" src="./assets/img/tabbar/profile_active.svg" alt="">
        <div slot="item-text">我的</div>
      </tab-bar-item>
    </tab-bar>
  </div>
</template>

<script>
import TabBar from "./components/tabbar/TabBar";
import TabBarItem from "./components/tabbar/TabBarItem";

export default {
  name: 'App',
  components: {
    TabBar,
    TabBarItem
  }
};
</script>

<style>
@import "./assets/css/base.css";
</style>

得到的效果如下:

image-20210911220501003

第122个视频 - TabBar的颜色动态控制

第1个问题 - 现在item永远都是活跃的,这个太糟糕

应该是点击了谁,谁处于活跃,谁就是红色的。

现在都是红色,是因为,在TabBarItem组件当中,我们的活跃属性是写死的。

image-20210911220753172

我们上面的isActive不能够写死。

要根据某个条件来判断,当前item是不是活跃的。

某个条件是什么条件?

在路由当中$route就表示当前活跃的路径组件映射对象。

我们可以拿到处于活跃的路由的path。

我们可以将item本身的path(这个是父组件传过来的link)。

和当前活跃路由的path是不是一回事。

这样就能够确定,当前的item是不是活跃的。

锚点:切记切记。这种结合路由判断是否活跃的小技巧。

image-20210911222728731

得到的效果如下:

image-20210911222750193

第2个问题 - 活跃的文字颜色现在是写死的哦

看看下面的图:

image-20210911222943858

我们活跃的文字颜色,直接是写死的。

这个是不好的。

如果人家用户传进来的active的图片,是蓝色,那肯定是需要活跃的文字颜色也是蓝色的。

不能够是红色。

他又不能够进入到你的封装好的组件当中,去修改颜色。

我们封装组件,就是希望所有的东西是动态的。

我希望别人用我们的TabBarItem的时候,动态传入颜色。

这个时候,我们需要从父组件当中动态传入样色,然后给我们的文字动态绑定样式。

代码如下:

image-20210911224023844

image-20210911224252226

这样做过之后,我们可以动态传入活跃文字颜色为蓝色:

image-20210911224218337

第123个视频 - 知识回顾

第1个问题: 我感觉App.vue当中代码有点多

想要把下面的内容抽离出去:

image-20210911224659112

我们在components文件夹下面创建MainTabBar.vue文件,然后把上面的红框当中的代码,都拷贝到MainTabBar.vue的template当中。

然后将script当中当中的导入代码,也拷贝到MainTabBar.vue当中,将TabBar和TabBarItem两个组件注册在MainTabBar组件当中。

最终得到的MainTabBar当中的代码是:

image-20210911225532073

然后我们的App.vue当中就变得非常简单:

image-20210911225616368

第2个问题 :知识回顾

image-20210911230028370

image-20210911230201989

image-20210911230334182

image-20210911230501927

image-20210911230528425

第124到140个视频与前面的视频重复

第124到第140个视频

第107到123个视频

重复。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-12 20:38:26  更:2021-09-12 20:38:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:28:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码