Vue前端框架实战手册——从入门到精通全攻略

文摘   职场   2024-06-05 00:17   广东  


序  言

摘要


第 1 章:Vue介绍



第 2 章:Vue常用指令



第 3 章:Vue指令进阶



第 4 章:computed和methods



第 5 章:Watch监听器



第 6 章:Vue生命周期



第 7 章:Vue常用事件



第 8 章:Vue项目工程化



第 9 章:Vue组件通信









第 10 章:VueRouter路由












第 11 章:ESLint代码规范



第 12 章:前端缓存



第 13 章:Vuex状态管理工具









第 14 章:AJAX



第 15 章:Vue+ElementUI实战



第 16 章:Vue+Echarts实战



第 17 章:作者介绍


吴灿锦,吉林财经大学2019级本科生,曾作为长春鹰迅网络科技有限责任公司CEO,带领鹰迅公司团队在“互联网 +"和"挑战杯"等竞赛中斩获3个国家级,11个省部级奖项。

目前在上市公司从事Java开发相关工作已经接近两年了,参与了两个千万级用户的分布式系统的开发和维护工作,在做项目期间,对Mysql优化,分库分表,多线程,分布式锁,分布式事务,Redis缓存,RabbitMQ,xxl-job,ElasticSearch,SpringCloud微服务框架以及前端的Vue框架都有比较深入的研究,积累了丰富的实践经验和良好的职业履历。

欢迎访问我的个人网站:
www.yxclass.net


第 1 章

Vue介绍


1.1、Vue简介

1.1.1、Vue简介


Vue是一套前端框架,免除原生JavaScript中的DOM操作,就跟Mybatis一样,可以简化jdbc代码编写的后端框架;Vue是前端的框架,是用来简化JavaScript代码编写的。


学习了Vue后,document这部分代码我们就不需要再写了。

Vue基于MVVM(Model-View-ViewModel)思想,实现模型数据和视图的双向绑定,将编程的关注点放在数据上

1.1.2、插值表达式


插值表达式是一种Vue的模板语法,我们可以用插值表达式渲染出Vue提供的数据。

语法格式:{{ 表达式 }}。

<h3>{{title}}<h3>
<p>{{nickName.toUpperCase()}}</p>
<p>{{age >= 18 ? '成年':'未成年'}}</p>
<p>{{obj.name}}</p>
<p>{{fn()}}</p>

1.2、MVC模型

要了解MVVM思想,必须先了解MVC思想:


Controller就是JavaScript的DOM代码,Model就是数据,而View是页面上展示的内容


1.3、MVVC

1.3.1、MVVC介绍


MVVM可以实现数据的双向绑定,双向绑定是指当数据模型数据发生变化时,页面展示的数据也会随之发生变化,如果表单数据发生变化,绑定的模型数据也随之发生变化,下图是MVVM三个组件图解。


上图中的Model就是我们的数据,View是视图,也就是页面的html标签,用户可以通过浏览器看到的内容;

Model和View是通过View Model对象进行双向绑定的,而ViewModel对象是Vue提供的,绑定了之后就可以实现Model数据变了,View页面展示数据进行相应的变化,而且这些变化都是自动完成的。

1.3.2、双向绑定代码示例


下图代码就是一个简单双向绑定的代码,输入框绑定了username模型数据,而在页面上也使用插值表达式绑定了username模型数据。


input输入框是视图,输入框后面的数据也是视图,第1个视图发生变化,就会影响模型M,模型变了就会影响第2个视图,第2个视图也发生变化,就是实现了MVVM,视图变了模型变,模型变了视图变。


如果使用MCV模型的话,需要先通过document.getElementById获取View输入框的数值,然后通过formDate.username去设置Model的数据值。


使用了Vue框架,通过Vue指令将视图和模型数据绑定好了之后,用户输入数值,模型里面数据就会自动更改。就不用做DOM的获取表单数据以及设置表单数据的操作了。

1.4、Vue快速入门

Vue使用起来是比较简单的,总共分为如下三步:

1.4.1、引入Vue.js文件


步骤1:新建HTML页面,通过<script>的src属性引入Vue.js文件。


1.4.2、创建Vue对象


步骤2:使用满参构造器创建Vue对象,el属性值为需要被Vue控制的代码块,在data()方法中通过rutrun关键字返回模型数据。


1.4.3、编写视图


步骤3:编写视图,在<body>标签被控制的代码块的选择器填写Vue对象el属性的值,这样Body代码块的视图就和Vue的数据模型关联起来了。


1.4.4、整体代码解释


创建好vue对象后,就可以在模型上面写一个input输入框,并绑定v-model,绑定好了之后就用一个插值表达式将模型数据取出来。这样input输入框的数据发生变化,模型的数据也会有相应的变化。模型一变,我们根据模型取出来的数据也会发生相应的变化。


第 2 章

Vue常用指令


2.1、内容渲染指令

内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。

2.1.1、v-html


使用语法:


 <p v-html="info">简介:</p>


类似 innerHTML,使用该语法,会覆盖 p 标签原有内容,并以HTML标签的样式呈现出来。





2.1.2、v-text


使用语法:


<p v-text="uname">hello</p>


类似 innerText,使用该语法,可以将 uame 值渲染到 p 标签中,覆盖 p 标签原有内容。

2.1.3、二者区别


v-text: 此指令用于将数据绑定到元素的textContent上,即它会替换元素内部的纯文本内容。Vue会确保所绑定的数据仅作为文本显示,不会被解释为HTML。这意味着任何HTML标签都会被原样输出,而不是被浏览器解析为标签。v-text是一种单向绑定,用于简单地显示数据,提高性能并避免XSS攻击风险。它提供了一种安全的方式来插入文本内容,而不用担心注入恶意HTML代码。

v-html: 与v-text相反,v-html指令允许你将数据绑定到元素的innerHTML上。这意味着传入的数据会被解析为HTML,如果数据包含HTML标签,这些标签会被浏览器解析并渲染出来,使得你可以动态插入一段HTML代码到页面中。由于v-html会执行HTML解析,因此使用它时必须格外小心,确保所插入的HTML内容是可信的,以防止XSS(跨站脚本攻击)。

2.2、条件渲染指令

条件判断指令,用来辅助开发者按需控制 DOM 的显示与隐藏。

2.2.1、v-show


1. 作用:
控制元素的可视状态:允许你基于数据模型中的布尔值来决定一个元素是否应该被用户看见。

2. 原理:
改变CSS的display属性:v-show通过修改元素的display样式属性实现显示与隐藏的切换,当条件为真时设置为默认的显示样式(如block、inline等),条件为假时则设置为none,使元素不占用页面布局空间。

3. 场景:
与v-if相比,v-show的一大优势在于其切换成本较低,因为它只是简单地切换CSS属性,而不会触发生命周期钩子函数,也不会造成DOM的重新渲染。因此,对于那些需要经常切换显示与隐藏状态的元素,使用v-show会更加高效和流畅。


2.2.2、v-if


功能:实现条件化的DOM渲染,即根据给定的条件逻辑来决定一个元素或组件是否应当被渲染到页面上。

原理:v-if执行的是更为彻底的条件控制,它会在每次条件变化时作出决策,根据条件真假动态创建或销毁DOM节点。这意味着,当条件不满足时,相应的元素不仅会被隐藏,还会从DOM树中移除,减少不必要的资源消耗和提高初次渲染的效率。

场景:特别适合于那些具有明确的“存在或不存在”状态,且不需要频繁切换的场景。例如,在页面加载时根据用户权限决定是否展示某个模块,或者根据网络请求的结果决定是否显示某些内容。由于v-if涉及实际的DOM操作,相较于v-show,在需要频繁切换显示状态的情况下可能会有更高的性能开销。

2.2.3、二者的区别


1. 渲染原理:
v-if:是惰性的,初始条件为假时,Vue不会渲染该元素,当第一次条件为真时,Vue才会渲染。之后当条件改变时,Vue会销毁并重新创建DOM元素,因此v-if需要较高的切换成本。
v-show:无论初始条件是什么,Vue都会渲染元素,并通过修改SCC的display属性来切换元素的可见性。这意味着v-show没有条件渲染的开销,但首次渲染时所有元素都会被处理,这可能导致初始渲染时间较长。

2. 性能考虑:
对于频繁切换的场景,v-show更为合适,因为它只是简单地切换CSS属性,避免了DOM的重建。
对于不常改变的状态,v-if更为高效,因为它避免了不必要的渲染操作和DOM操作开销。

3. 内存占用:
v-if在条件为假时不创建DOM元素,因此减少了内存占用。
v-show始终创建DOM元素,即使它们被隐藏,因此在大量元素需要隐藏时可能会占用更多内存。

4. 编译与生命周期:
使用v-if时,元素及其内部的指令和组件只有在条件为真时才会被编译和挂载。这影响了它们的生命周期钩子函数,只有符合条件时才会被调用。
v-show则总是被编译并保留在DOM中,其内部的组件总是被初始化,只是简单地改变CSS来控制显示。

5. 使用场景总结:
当你需要根据条件展示元素,并且这个条件不会频繁改变时,推荐使用v-if,以减少不必要的DOM操作和提升性能。
如果元素需要根据条件频繁切换显示与隐藏,使用v-show会更为合适,因为它避免了DOM的重新渲染,提供了更流畅的用户体验。


2.3、事件绑定指令

2.3.1、点击事件语法格式


使用Vue时,如需为DOM注册事件,及其的简单,语法如下:

<button v-on:事件名="内联语句">按钮</button><button v-on:事件名="处理函数">按钮</button><button v-on:事件名="处理函数(实参)">按钮</button>v-on: 简写为 @

2.3.2、应用案例



2.4、属性绑定指令

1. 语法:


v-bind:属性名=“表达式”// v-bind可以省略,简写成下面的格式:属性名=“表达式”


2. 场景
有一个图片,它的 src 属性值,是一个图片地址这个地址在数据 data 中存储。则可以这样设置属性值:



2.5、双向绑定指令

所谓双向绑定就是:

1. 数据改变后,呈现的页面结果会更新;
2. 页面结果更新后,数据也会随之而变。



作用:给表单元素(input、radio、select)使用,双向绑定数据,可以快速 获取 或 设置 表单元素内容

语法:

v-model="变量"



需求:使用双向绑定实现以下需求。

1. 点击登录按钮获取表单中的内容;
2. 点击重置按钮清空表单中的内容。





2.6、列表渲染指令

2.6.1、v-for介绍


Vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。

语法格式:

(item, index) in arr

语法解释:

item 是数组中的每一项;
index 是每一项的索引,不需要可以省略;
arr 是被遍历的数组。

2.6.2、示例代码一






2.6.3、v-for中的key


语法:key="唯一值";

作用:给列表项添加的唯一标识,便于Vue进行列表项的正确排序复用。

为什么加key:Vue 的默认行为会尝试原地修改元素(就地复用);

实例代码:


注意:
1. key 的值只能是字符串或数字类型;
2. key 的值必须具有唯一性;
3. 推荐使用  id 作为 key,确保唯一性,不推荐使用 index 作为 key,因为索引值会根据增删自动发生改变的。

2.6.2、示例代码二






第 3 章

Vue指令进阶


3.1、v-bind进阶

为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名 和 style 行内样式进行控制 。

3.1.1、v-bind控制class样式


语法格式:




tab栏切换导航高亮的实现:




li a 和 li a.active 是CSS选择器,分别用来设置未激活和激活状态下列表项链接的样式。


在Vue.js应用程序中,通过JavaScript动态地为满足条件的链接添加 .active 类,使相应列表项的链接背景变为红色,文本颜色变为白色。这样就实现了点击列表项时的高亮效果。




3.1.2、v-bind操作style样式


语法格式:




进度条的实现:




:style="{ width: percent + '%' }" 是 Vue.js 中的一个指令,用于动态地绑定内联样式到HTML元素上。

当 percent 的值发生变化时,例如通过点击按钮触发事件并更改 percent 的值,该元素的宽度将会根据这个新的百分比值自动调整。例如,如果 percent 是 50,那么对应的inner选择器控制的 CSS 样式将是 width: 50%,这意味着进度条的填充部分将占其父容器宽度的 50%。




3.2、v-model进阶

常见的表单元素都可以用v-model绑定是视图和模型数据,它会根据控件类型自动选取正确的方法来更新表单素的值。

3.2.1、input输入框


input输入框的type可以选择text文本输入,password密码输入,radio单选和checkbox多选等类型,value是提交给后端的值。

3.2.2、select下拉框


option需要设置value值,提交给后台。

3.2.3、代码示例







3.3、自定义指令

3.3.1、自定义指令介绍


内置指令:v-html、v-if、v-bind、v-on...这都是Vue给咱们内置的一些指令,可以直接使用。

自定义指令:同时Vue也支持让开发者,自己注册一些指令。这些指令被称为自定义指令,每个指令都有自己各自独立的功能

3.3.2、全局注册自定义指令


全局注册的指令在整个应用范围内都是可用的,这意味着你可以在任何一个Vue实例的模板中使用它。

例子:创建了一个全局自定义指令v-my-directive,当它被应用到元素上时,在元素插入DOM时会改变其字体颜色为指令值。


3.3、使用自定义指令


注意:在使用指令的时候,一定要先注册,再使用,否则会报错,注册指令时不用加v-前缀,但使用时一定要加v-前缀
使用指令语法:v-指令名。如:

 
3.3、局部注册自定义指令


局部注册的指令仅在其所在组件的作用域内有效,不适用于外部组件。


例子:创建一个v-my-local-directive局部自定义指令,指令只在当前组件内部生效,当该指令作用于<div>元素时,会在元素上添加一个类名custom-class。


第 4 章

computed计算属性


4.1、computed计算属性

3.3.1、computed计算属性介绍


Computed Properties计算属性是用来根据组件内部响应式数据(通常是 data 中的属性)的变化来动态计算并返回新值的一种特性。计算属性的结果会被缓存起来,只有当依赖它的响应式属性发生变化时,才会重新计算。这不仅简化了模板中的复杂逻辑,而且提高了性能,因为它避免了不必要的重复计算。

3.3.2、语法和注意点


1.声明在 computed 配置项中,一个计算属性对应一个函数;
2.使用起来和普通属性一样使用  {{ 计算属性名}};
3.computed配置项和data配置项是同级的;
4.computed中的计算属性虽然是函数的写法,但他依然是个属性;
5.computed中的计算属性不能和data中的属性同名;
6.使用computed中的计算属性和使用data中的属性是一样的用法;
7.computed中计算属性内部的this依然指向的是Vue实例。

3.3.3、案例代码









4.2、computed和methods对比

4.2.1、ComputedProperties作用


计算属性用于封装一段针对 响应式数据 的处理逻辑,它可以基于 Vue 实例中的多个数据属性自动派生出一个新的计算结果,并保持响应性。
计算属性的作用

4.2.2、Computed Properties语法


1. 在 Vue 组件的 computed 配置项中定义计算属性。

2. 作为属性直接使用:
在 JavaScript 中使用计算属性:this.计算属性名;
在模板中通过 {{ 计算属性名 }} 来插入计算属性的值。

4.2.3、methods作用


Methods 提供给 Vue 实例一些可调用的方法,它们主要用于执行特定的 业务逻辑,包括但不限于处理数据转换、执行异步操作、触发某些动作等。
Methods作用

4.2.4、methods语法


1. 写在methods配置项中
2. 作为方法调用

调用方法时:在 JavaScript 中通过 this.方法名() 来执行方法。
在模板中可以通过 {{ 方法名() }} 来调用方法并渲染结果,或者@事件名="方法名"。

在模板中调用方法会导致每次页面渲染都会执行该方法;另外,在事件处理器中绑定方法更为常见,例如:<button @click="方法名">...</button>,这种方式仅在触发相应事件时执行方法。

4.3、综合案例-成绩管理

4.3.1、原型页面



4.3.2、功能描述


1.渲染功能
2.删除功能
3.添加功能
4.统计总分,求平均分

4.3.3、思路分析


1.渲染功能  v-for  :key  v-bind:动态绑定class的样式;
2.删除功能 v-on绑定事件, 阻止a标签的默认行为;
3.v-model的修饰符 .trim、.number、判断数据是否为空后 再添加、添加后清空文本框的数据;
4.使用计算属性computed 计算总分和平均分的值。


4.3.4、代码实现



第 5 章

Watch监听器


5.1、watch的作用

watch监听器的主要作用是监视数据变化,执行一业务逻辑或异步操作。总的来说就是当data()里面的值发生变化时,就会执行watch的方法。

5.2、语法

1. watch同样声明在跟data同级的配置项中;
2. 简单写法:简单类型数据直接监视;
3. 完整写法:添加额外配置项。


5.3、监听单个数据属性

监听 message 属性的变化,并在变化时更新 reversedMessage 为其反转的字符串。


5.4、监听多个数据属性

同时监听 firstName 和 lastName 的变化,并且 firstName 的监听器在初始加载时立即执行。

需要监听器立即执行就要设置immediate的值为true,当组件实例被创建并开始初始化时,即使firstName尚未发生改变,也会立即调用handler函数。这对于某些需要在数据初始化时就进行计算或处理的场景非常有用。


5.5、深度监测数组和对象


在这个示例中,我们深度监听 user 对象,这意味着当 user 对象内部的 name 或 address 属性及其子属性有任何变化时,都会触发监听器。

在这个例子中,如果没有设置deep的值为true,那么只有当整个user对象被替换(即整个对象的引用发生了变化)时,handler函数才会被调用。但是,如果设定了deep的值为true,那么无论是user对象本身的属性(如name)发生变化,还是其嵌套对象address的属性(如street或city)发生变化,handler函数都会被调用。

5.6、使用watch进行表单验证

使用 watch 来实时监听和验证表单字段,当这些字段的值发生变化时,就会调用相应的验证方法。


在这个示例中,onSubmit 方法是在表单提交时调用的。然而,由于我们已经在 watch 中设置了对 user.email 和 user.password 的监听,并且在它们的值发生变化时调用了相应的验证方法(validateEmail 和 validatePassword),所以每次用户在表单中输入邮箱地址或密码时,都会实时进行验证。

虽然前面已经对表单字段进行校验,但是当用户点击“Submit”按钮提交表单时,还需要在 onSubmit 方法内部再做一次最终的完整验证,以确保表单提交前所有验证条件都满足。

第 6 章

Vue的生命周期


6.1、Vue生命周期

Vue生命周期:就是一个Vue实例从创建到销毁的整个过程。


生命周期有创建、挂载、更新和销毁四个阶段。

1.创建阶段:创建响应式数据;
2.挂载阶段:渲染模板;
3.更新阶段:修改数据,更新视图;
4.销毁阶段:销毁Vue实例。


6.2、Vue生命周期钩子

6.2.1、生命周期钩子函数


Vue生命周期过程中,会自动运行一些函数,被称为"生命周期钩子函数",让开发者可以在“特定阶段”运行自己的代码。



Vue生命周期钩子函数有八个:

before Create;
created;
before Mount;
mounted;
before Update;
update;
before Destroy;
destroyed;


6.2.2、在created中发送请求


在Vue组件的生命周期中,如果需要在页面渲染之前进行数据准备工作或发起异步请求,通常在 created 钩子中执行

因为created 生命周期钩子在组件实例被Vue完全创建后调用,这意味着:组件的选项对象如 data、computed、watch、methods 等已经被设置好了。

数据双向绑定已建立,数据观测系统已经生效,可以通过 this 访问组件内的响应式数据并对其进行操作。

然而,此时组件的模板还没有被渲染成HTML,也未挂载到DOM中,所以还不能直接操作DOM节点,但可以先给后端发请求获取数据


6.2.3、在mounted中获取焦点


焦点(Focus)是指当前活动的或用户正在与其交互的UI元素,即用户可以通过键盘输入信息或进行操作的元素。拥有焦点的元素通常具有视觉上的高亮或或者光标闪动等标识,以表明它是当前活动的对象。


需求:在页面定义一个搜索框,一旦页面挂载完成,搜索框就自动获取焦点,让用户直接输入搜索内容。



代码解释:一旦Vue实例挂载完成并渲染到DOM中,就会立即执行mounted()方法。方法内通过document.querySelector('#inp')选取ID为inp的input元素,并调用.focus()方法使其获得焦点。这意味着当整个Vue实例挂载完成后,搜索框会自动获取焦点,用户可以直接输入搜索内容。


6.2.4、created和mounted总结


总的来说,初始化渲染请求通常在 created 阶段发出以便尽早获取数据,而操作DOM则应该在 mounted 阶段进行,因为此时DOM元素才渲染完成,就可以操作DOM元素。

6.2.5、在beforeDestroy中释放资源


在Vue.js的生命周期钩子中,beforeDestroy 是一个在组件实例销毁之前被调用的方法。当一个组件不再需要时,例如用户导航离开该页面或者父组件解除了包含当前组件的引用,Vue会触发一系列的清理工作,而 beforeDestroy 生命周期钩子就是在这些清理工作开始前执行的。

在这个钩子函数中,开发者可以进行一些必要的清理操作,比如清除定时器、取消网络请求、解绑事件监听器,或者像下述示例中的情况——释放ECharts图表实例所占用的资源。

对于ECharts图表来说,它在初始化时会在DOM元素上绑定大量事件和创建内部数据结构,如果不手动清理,在某些情况下可能会导致内存泄漏。因此,在 beforeDestroy 钩子中,我们通常会调用ECharts实例的 dispose 方法来销毁图表实例并释放其占用的资源,确保当组件不再使用时,相关的DOM节点和JavaScript资源能够被正确地清理掉,从而保持应用程序的良好性能和健康状态。


第 7 章

Vue常用事件


7.1、点击事件

Vue.js 中的点击事件绑定通常使用 v-on:click 或其缩写 @click 指令来实现。

7.1.1、基础点击事件绑定



7.1.2、传递参数给点击方法




7.2、鼠标移入移出事件

移入事件:@mouseover;
移出事件:@mouseout;





7.3、键盘事件

7.3.1、按下Enter键事件


在输入框上添加了 @keydown.enter="search" 事件监听器,这样当用户按下 Enter 键时,就会调用 search 方法。





7.4、表单事件

7.4.1、@submit表单提交事件


@submit 事件用于监听表单提交动作。当用户点击表单内的提交按钮或者通过 JavaScript 触发表单的 submit 事件时,@submit 事件处理器会被调用。通常用来执行验证、清理数据、向服务器发送请求等操作。




@submit.prevent 是 Vue 的事件修饰符,.prevent 用于阻止表单的默认提交行为,即防止页面跳转或重新加载。

当表单提交时,会调用 onSubmit 方法,在该方法内可以进行表单字段的验证,并根据验证结果决定是否执行下一步操作(如模拟发送登录请求)。

7.4.2、@input输入框事件


使用 @input 事件可以实时监听用户输入的变化,并进行相应的处理,每当输入框的内容发生变化时,即使用户只是输入了一个字符,@input事件也会立即触发。这个事件对于实时搜索、数据验证、过滤或联动更新特别有用。

请注意,input 事件在一些特殊情况下可能无法触发,如通过脚本改变输入框的值时,可以使用 change 事件作为备选。



现实时搜索框建议的功能的实现:






7.4.2、@change


@change 事件主要用于表单元素,特别是像 input、select、textarea 或者自定义组件等,它会在表单元素值发生变更并且元素失去焦点(即 blur)时触发。

@change 事件不像 @input 那么频繁,它是在用户完成一次输入操作后才触发,这对于那些不需要实时响应每个字符变化,而只需要在输入内容有实质性更改时进行处理的场景尤为适用。





7.4.3、@blur表单失去焦点验证


@blur 是一个原生HTML事件,它会在元素失去焦点时触发,也就是说,当用户从该元素(比如输入框)离开并将焦点移动到其他元素上时,该事件会被触发。

不论输入框的值是否有变化,只要元素失去了焦点,@blur 事件都会执行。



电话号码验证:


7.4.4、自定义表单控件事件绑定


在Vue中,我们可以使用v-on,简写为@,指令来绑定自定义表单控件的事件。



CustomInput.vue子组件:




App.vue父组件:




在此示例中,我们创建了一个名为CustomInput的自定义表单控件,其中包含一个文本输入框。当输入框内容变化时,子组件会触发一个自定义事件input-change并向父组件传递新的值。父组件通过监听这个自定义事件并对新值做出响应,实现了与自定义表单控件之间的通信和数据同步。


7.4.5、表单事件总结


@submit:事件发生在<form>元素上,当用户点击表单内的提交按钮或者通过JavaScript调用表单的submit()方法时触发。

@input 事件用于实时监听任何表单控件(特别是<input>、<textarea>等)内容的变化。
当用户在输入框中每输入一个字符,或者通过JavaScript改变元素的value值时,都会触发@input事件。
在Vue中,常常与v-model搭配使用,实现双向数据绑定的同时进行实时的数据验证和联动操作。

@blur 事件(也称为 focusout)发生在所有可获得焦点的元素上,如<input>、<textarea>、<select>等,当元素失去焦点(用户点击页面上其它地方或按Tab键切换焦点)时触发。
常用于进行诸如表单验证、清理临时数据等操作,无论表单字段的值是否改变,只要元素失去焦点就会触发。

@change 事件在某些表单控件上(主要在<input>、<select>和<textarea>)表示内容发生变更且失去焦点时触发。
与@input不同的是,@change只会在元素值改变且失去焦点时才触发。

第 8 章

Vue项目工程化


8.1、工程化开发和脚手架

8.1.1、前端工程化介绍


Vue前端开发工程化,是指在Vue.js框架基础上,采用一系列自动化工具和最佳实践,如Webpack进行模块打包、Babel进行JSX/ES6转译、Vue CLI创建和配置项目、Vuex管理状态、Vue Router处理路由等,以提升开发效率、保证代码质量、实现高效协作。通过组件化开发、持续集成/持续部署(CI/CD)等流程,将Vue应用从设计、开发、测试到上线的全生命周期进行规范化、自动化管理。

8.1.2、Vue脚手架


Vue脚手架,即Vue CLI,是Vue.js官方提供的一个强大且灵活的命令行工具,用于快速初始化并搭建Vue.js项目结构。通过预设模板和丰富的可配置选项,Vue CLI能够一键生成包含Webpack配置、Vue Router、Vuex、 ESLint等现代化前端开发所需的项目骨架,极大提升了开发效率和团队协作一致性。同时,它还支持自定义和扩展插件系统,满足不同项目的特定需求,是Vue.js生态中不可或缺的工程化工具。

8.1.3、Vue Cli安装


安装Vue Cli前,需要确保已经正确安装了Node.js和npm。可以通过在命令行窗口输入node -v和npm -v来检查是否已经安装,如果已经安装,会显示相应的版本号。


// 安装最新版本npm install -g @vue/cli
// 卸载命令npm remove -g @vue/cli// 安装指定版本命令npm install -g @vue/cli@4.1.2
//查看vue/cli版本:vue --version

8.1.4、创建Vue项目


1. 创建Vue项目:

//打开cmd窗口vue ui//在弹出的可视化界面选择项目需要的配置

2. 启动项目:

yarn serve 或者 npm run serve//启动命令不固定,具体找package.json
//例如测试环境命令npm run serve-dev
//生产环境启动命令npm run serve-prod


8.2、项目目录和运行流程

8.2.1、项目目录介绍



1. views是网页的页面。
2. 一个页面通常有多个组件。
3. 数据状态管理就是说一个页面页面通常有多个组件,多个组件之间进行数据交互就要使用到store的数据管理。比如说一个子组件更新一个数据,如何去通知另外一个组件,这就可以通过store的数据状态管理,让所有的组件都可以监听store这里面的内容,store这里面的数据内容更新之后,就可以通知所有的组件,这样就可以达到各个组件之间的数据同步。
4. App.vue是入口界面,这个页面最终会在main.js中被调用,main.js就是整个vue项目的入口。

8.2.2、运行流程



8.3、组件化开发

8.3.1、组件化开发介绍


组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。

好处:便于维护,利于复用,提升开发效率。
组件分类:普通组件、根组件。

比如:下面这个页面,可以把所有的代码都写在一个页面中,但是这样显得代码比较混乱,难易维护。我们按模块进行组件划分,就会简单很多。

8.3.2、App.vue根组件


App.vue是整个应用最上层的组件,包裹所有普通小组件。


8.3.3、组件构成部分


Vue.js 单文件组件(SFC)的核心构成要素如下:


1. Template部分:负责定义组件的HTML结构,这部分相当于组件的视图层,每个.vue文件中必须且只能有一个顶级根元素,用于描绘组件的布局和内容。

2. Script部分:承载组件的JavaScript逻辑,这里可以定义组件的数据(data)、计算属性(computed)、方法(methods)、生命周期钩子函数(lifecycle hooks)以及其他Vue选项(props、watch、mixins等),它是组件的行为层和数据层。

3. Style部分(style):用于编写组件级的CSS样式,支持原生CSS以及各种预处理器如Less、Sass等。若要使用Less,需先安装对应的预处理器及loader(例如less和less-loader),并在<style>标签上通过lang="less"属性指定语言类型,以便Webpack或其他构建工具在编译过程中将Less代码转换为CSS。

8.3.4、让组件支持less


在Vue.js项目中,让组件支持LESS是指在编写组件的样式时,允许使用LESS(Leaner Style Sheets)这一预处理器的语法特性。LESS 是 CSS 的一种扩展形式,它提供了诸如变量、嵌套规则、混合(mixin)、运算符、函数等功能,使样式表的编写更具表现力、简洁性和可维护性。


让组件支持less步骤:


步骤1: 安装less依赖包。


npm install less less-loader -D  # 使用npm# 或者yarn add less less-loader -D   # 使用yarn

步骤2:在组件的style标签加上lang="less",开启less功能。



8.3.5、组件命名规则


组件名规范 ,大驼峰命名法, 如:
TodoHeader;
TodoFooter.vue。



8.4、Vue组件的注册

8.4.1、局部注册Vue组件


局部注册是指在一个Vue组件内部定义并注册其他子组件,这些子组件的作用域仅限于当前父组件及其嵌套组件中。局部注册的组件不会在整个Vue应用范围内可用,只有在其所在的父组件模板中才能被引用。
Vue局部注册介绍


局部注册Vue组件步骤:


步骤1:在父组件中使用import关键字导入需要使用的组件。


步骤2:在父组件的export default对象内的compoents属性中注册子组件。



步骤3:在父组件的模板中,可以像使用HTML元素一样使用这个局部注册的子组件。



8.4.2、全局注册Vue组件


全局注册的组件,在项目任何一个Vue实例或组件都能够访问和使用这个组件,而无需在每个单独的组件内部进行局部注册。
Vue全局注册介绍
全局注册Vue组件步骤:

步骤1:创建一个.vue单文件组件:




步骤2:在main.js中进行全局注册:





步骤3:一旦组件被全局注册,你在整个项目中的任何组件模板中都可以像使用内置HTML标签一样使用它。



8.5、scope解决样式冲突

8.5.1、样式冲突介绍


在Vue组件中编写样式时,默认情况下,如果样式没有设置scoped作用域,那么这些样式不仅会应用于全局所有的组件,因此很容易造成多个组件之间的样式冲突问题。

1. 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响。
2. 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件。


8.5.2、scope原理


1. 当前组件内标签都被添加data-v-hash值的属性;
2. css选择器都被添加 [data-v-hash值] 的属性选择器、


8.6、data必须是一个函数

在Vue.js中,组件的data选项设计为必须是一个返回对象的函数,而非直接提供一个对象。这一设计原则的根本目的是为了保证每个组件实例都有自己独立且隔离的数据副本,避免数据共享带来的潜在问题。

具体来说,每当Vue.js创建一个新的组件实例时,它会调用data函数,并以返回的对象作为该组件实例的数据源。这样一来,即便多次实例化同一个组件,各个实例间的数据也不会互相影响,从而维持数据的独立性和状态管理的清晰性。


第 9 章

Vue组件通信


9.1、组件通信介绍

9.1.1、组件通信介绍


Vue组件通信,是指在Vue应用中,因组件间的数据都是独立的,无法直接访问其他组件的数据,当需要实现不同组件间数据共享和传递时,就必须通过有效的组件通信方式进行数据传递。


9.1.2、组件关系分类


组件关系有两种,分别是父子关系和非父子关系。



9.1.3、通信解决方案


1. 父子关系的组件可以通过props和$emit进行通信。
2. 非父子关系的组件可以通过provide & inject和eventbus进行通信。


9.2、父子组件通信

9.2.1、父子组件通信流程


1. 父组件通过 props 将数据传递给子组件;
2. 子组件利用 $emit 通知父组件修改更新。


9.2.2、父组件向子组件传值步骤


步骤1:给子组件以添加属性的方式传值;

步骤2:子组件内部通过props接收父组件传过来的值;


步骤3:在子组件的模板中直接使用 props接收的值;


步骤4:父组件通过子组件标签名进行传值;


9.2.3、子组件向父组件传值步骤


1. $emit触发事件,给父组件发送消息通知;


2. 父组件监听$emit触发的事件,并提供处理函数,在函数的形参中获取传过来的参数;


9.3、props

9.3.1、props介绍


Props是Vue组件上预设的自定义属性接口,用于外部向组件内部传递数据。

Props作用是扮演者父组件与子组件之间桥梁的角色,其核心功能在于安全、有序地向子组件传递所需要的数据。

9.3.2、props的特点


1. 多元性:Props支持传递任意数量的属性,即可以设置多个不同的props以满足不同数据的传递需求。

2. 多样性:Props能够传递任意类型的变量,包括但不限于字符串、数字、布尔值、对象、数组甚至是函数等,为组件间的数据交互提供了极大的灵活性。

9.3.3、props校验


Vue.js 中的 props 校验是一种机制,它允许组件在接收来自父组件传递的属性(props)时,对这些属性的值进行合法性检查。这种校验有助于确保组件正确接收和使用数据,提高了代码健壮性和可维护性。



1. 语法:




2. 类型校验案例:

在组件定义中,可以为props指定预期的数据类型,如String、Number、Boolean、Array、Object、Function等。如果传入的props值类型与声明不符,Vue会发出警告提示。




3. 高级校验:

Vue除了基本类型外,还支持自定义校验函数,可以编写更复杂的逻辑来验证props是否符合业务需求。




注意点:

I. default和required一般不同时写,因为当时必填项时,肯定是有值的;
II. default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值。



4. 在Vue 3中,使用新的Composition API时,props的校验还可以通过defineProps进行:


9.3.4、props和data的共同点


Props和Data都是Vue组件中两种关键的数据来源,分别负责从外部环境(父组件或其他外部源)和内部初始化提供组件所需的运行数据。

9.3.5、props和data的区别


data 属性:组件内部定义的数据,具有高度自主权。组件可以直接修改data中的数据,并基于这些数据驱动视图的更新。这些数据仅对该组件自身可见,且完全受控于组件内部逻辑。

props 接收:组件从外部(父组件)接收的数据,具有约束性和保护性。组件不能直接修改props传递进来的数据,遵循“单向数据流”的原则。这是因为props数据来源于父组件,如果子组件随意修改,可能造成数据流向混乱,降低代码可预测性。

9.3.6、单向数据流


在Vue中,数据流动遵循严格的单向数据流原则。这一原则体现在props的使用上,即数据通常是由父组件流向子组件。当父组件中props的数据发生更新时,这些变化会自动向下传播到使用该props的子组件中,触发子组件视图的重新渲染。但是,子组件不能直接修改props的原始值,而是应该通过事件触发回调等方式,让父组件去更新数据,从而维持数据流向的单一性和可控性。这样的设计有利于提高代码的稳定性和可维护性。

9.4、非父子组件通信

9.4.1、Event Bus事件总线


Event Bus(事件总线)在 Vue.js 中主要用来解决非父子组件间的通信问题。它提供了一种简便的方式让不在同一个组件树层级上的两个或多个组件能够互相传递信息,而在更复杂的项目中,通常推荐使用 Vuex 进行状态管理。


实现步骤:


步骤1:创建一个全局可访问的 Vue 实例作为事件总线。




步骤2:接收组件监听事件,在需要接收消息的组件(例如:A组件)中,在适当生命周期钩子(如 created 或 mounted)内监听事件总线上的特定事件。




步骤3:在需要发送消息的组件(例如:B组件)中,通过调用事件总线的 $emit 方法来触发已定义的事件并传递数据。


这样,当点击 B 组件中的按钮时,会触发 sendMsg 事件并将消息内容传递给 A 组件,A 组件接收到消息后更新其内部状态。通过这种方式实现了非父子组件间的通信。

9.4.2、provide和inject


1. provide和inject介绍:

Vue.js 提供了一对属性 provide 和 inject 用于实现非父子组件之间的通信。这种方式特别适用于跨越多层嵌套的组件之间传递数据或者服务。


2. provide和inject作用:

provide和inject作用是跨层级共享数据,允许祖先组件向任意层级的后代组件提供数据,无需两者之间有直接的父子关系。


3. 使用场景:




4.代码流程:

步骤1:在祖先组件中,通过 provide 函数提供数据。


步骤2:在需要使用这些数据的子/孙组件中,通过 inject 选项指定所需注入的属性名称。


9.5、表单类封装

9.5.1、需求


实现子组件和父组件数据的双向绑定 ,实现App.vue中的selectId和子组件选中的数据进行双向绑定。



详细需求描述:

当在 BaseSelect 组件中选择不同的城市时,所选城市的值会通过 @change 事件触发 onSelectChange 方法,进而通过 $emit('input', value) 把选中的值传递给父组件 App,实现双向绑定。同时,当父组件 App 中的 selectId 发生变化时,也会同步到子组件 BaseSelect 的 selectedOption。

9.5.2、实现步骤


步骤1:在父组件使用 v-model 与子组件进行双向绑定。




步骤2:在子组件的select添加v-model属性,并监听change事件,当下拉框的值发生改变,且失去焦点时通过emit把数据传给父组件。并且props接收父组件传过来的值,最后通过watch监听props里面的值,当props中的value变化时,同步到selectedOption。


9.5.3、自定义组件实现v-model介绍


在Vue中,input事件通常与表单元素(如输入框、选择框等)相关联,当表单元素的值发生变化时,就会触发input事件。对于自定义组件实现v-model(即双向绑定),Vue推荐使用input事件来模拟原生表单元素的行为。

在上述场景中,子组件BaseSelect需要实现与父组件的双向绑定,按照Vue的v-model原理,子组件需要监听自身的改变,并通过$emit方法触发一个名为input的事件,将新的值作为参数传递给父组件。父组件监听这个input事件后,就可以接收到子组件中被选中的城市ID,并更新自己的数据模型(这里是selectId)。

v-model自定义组件绑定时,父组件给子组件传输数据的时候props的属性固定是value。所以在实际开发中一般使用.sync修饰符代替v-model,因为。sync可以自定义属性名。

9.6、sync修饰符

9.6.1、sycn介绍


.sync 修饰符是 Vue 提供的一个便捷方式,用来简化子组件与父组件之间双向绑定 props 的过程。它使得子组件可以直接修改父组件传入的 props,并将更改后的值同步回父组件

9.6.2、sycn应用场景


例如,在封装一个基础弹框组件 BaseDialog 时,常常有一个 visible 属性,用于控制弹框是否显示(true 显示,false 隐藏)。通过 .sync 修饰符,可以让子组件在内部自行改变 visible 属性的值,并确保这个变化能够反映到父组件的状态中。

9.6.3、sycn本质


.sync 修饰符实际上是 Vue 编译器在编译时自动转换为 v-bind 和相应的 v-on 事件监听器的简写形式。当你在父组件中使用 :visible.sync="isShow" 时,Vue 自动处理了以下两件事:

1. 将 isShow 的值传递给子组件作为 visible prop。
2. 添加监听子组件发出的 update:visible 事件,并在事件回调中更新 isShow 的值。

9.6.4、代码示例


父组件:




子组件:子组件需要在适当的地方通过 $emit 触发 update:visible 事件,并将新的 visible 值作为参数传递出去。


9.6.5、完整代码


父组件代码:




子组件代码:BaseDialog 组件接收一个布尔类型的 isShow prop,用于控制对话框的显示/隐藏。当用户点击关闭按钮时,调用 closeDialog 方法,该方法通过 $emit 触发 'update:isShow' 事件,并把对话框的可见性设置为 false,实现与父组件的双向绑定效果。


9.7、ref和$refs

9.7.1、功能和作用


ref 是 Vue.js 提供的一种内置属性,它允许开发者在模板中为某个 DOM 元素或者组件赋予一个引用名称。而 $refs 则是一个特殊的对象,它在 Vue 实例挂载完成后存储了所有带有 ref 属性的元素或组件实例的引用。

9.7.2、优势和特点


查找范围: ref 的查询范围仅限于当前 Vue 组件的模板树中,相比于全局的 document.querySelector() 更加精确且不受外部环境影响,确保获取的是组件内部相关的 DOM 或者组件实例。

9.7.3、代码示例一



给el-form表单注册成一个实例,实例名就叫ref,相当于java的对象一样,注册成实例的好处是在方法中通过$refs[表单名]拿到表单中的数据。




表单校验代码示例:


9.7.4、代码示例二


父组件代码:




子组件代码:


9.8、异步更新和$nextTick

9.8.1、异步更新


Vue采用异步更新策略来提高性能。当你修改了组件的数据,Vue并不会立即重新渲染和更新DOM,而是将这个变化记录下来,等到所有的数据变化都处理完,并且当前JavaScript执行栈清空后,再进行一次性的DOM更新。这种方式减少了不必要的重渲染,提高了应用运行效率。

9.8.2、$nextTick


$nextTick 是Vue提供的一个实用方法,它接收一个回调函数作为参数,并在Vue完成下一次DOM更新循环后执行这个回调。这意味着你可以使用$nextTick来确保在数据变化后,DOM已经是最新的状态,这时再执行对DOM的操作或者读取DOM信息是安全的。

9.8.3、代码示例


需求:编辑标题,点击编辑,大标题和编辑按钮不显示,出现一个编辑框,并且让编辑框立刻获取焦点。


代码实现:




补充说明:setTimeout()也可以实现,由于 setTimeout 依赖于固定的延迟时间,如果时间设置得太短,可能在 DOM 还未完成更新时就执行了聚焦操作,导致操作失效。反之,如果设置得过长,则用户会感受到不必要的延迟,影响交互体验


9.9、Slot插槽

9.9.1、插槽的作用


在Vue中,默认插槽(Default Slot)提供了一种方式,允许你在封装组件时保留一个可替换的部分,使得组件的使用者能够插入自定义内容。


9.9.2、删除对话框组件需求描述


需求:在页面中显示一个对话框,将这个对话框封装成一个组件,组件允许自定义内容并通过事件处理来自外部的删除确认操作。


9.9.3、删除对话框代码实现


MyDialog子组件:




App.vue页面父组件代码:


9.9.4、具名插槽语法


Vue的具名插槽赋予组件强大定制性,让外部使用者能针对内部不同区域插入自定义内容,尤其适用于多区域填充的场景。


通过template标签包裹需要分发的结构,通过v-slot:给插槽起一个名字,v-slot:的简单写法为#。




一旦插槽定义了名字,就是具名插槽,只支持定向分发。


9.9.4、表格数据组件需求描述


表格,每条表格数据都有一个操作列,在操作列点击查看会打开表格详细的数据弹窗。

9.9.5、表格数据组件代码实现


步骤1:创建一个CustomDialog.vue对话框子组件来展示表格数据。




步骤2:ParentComponent.vue父组件中展示一个表格,并使用CustomDialog组件来显示选中行的详细信息。


第 10 章

VueRouter路由


10.1、单页和多页应用程序

10.1.1、单页应用程序介绍


单页应用程序(Single Page Application,简称 SPA)是一种现代Web应用设计模式,其中用户与应用程序的交互在一个单一的HTML页面中完成,而无需传统意义上的页面跳转。所有内容的更新和交互都是通过AJAX异步数据交换和前端JavaScript处理实现的,从而实现了页面的即时更新,给用户带来接近原生应用的流畅体验。SPA减少了页面加载的次数,提高了用户体验,同时也促进了前后端的分离开发模式,前端负责用户界面和交互逻辑,后端则专注于数据处理和API接口的提供。

10.1.2、单页应用程序应用场景


1. 系统及内部工具:对于需要复杂用户交互、高效率操作反馈的系统类应用和企业内部工具,如项目管理软件、数据分析平台等,SPA能够提供流畅无刷新的用户体验。
2. 文档与知识库:在线文档阅读器、技术手册、教程网站等,SPA便于实现动态加载内容、搜索过滤等功能,提升用户查阅效率。
3. 移动端优化站点:考虑到移动设备的性能限制和用户对快速响应的期待,SPA通过减少页面跳转提高移动端浏览体验,特别适用于原生APP替代方案或响应式设计的Web应用。

10.1.3、多页应用程序介绍


多页应用程序(Multi-Page Application,简称 MPA)是Web开发的传统模式,每个功能或用户操作通常对应一个独立的HTML页面。与SPA不同,MPA在用户导航至不同页面时,会触发完整的页面加载过程,包括HTML、CSS、JavaScript等资源的重新请求和渲染。Vue框架虽然常用于构建SPA,但同样可以应用于构建结构化的MPA,通过路由管理实现多个页面之间的跳转,保持页面间状态的独立性。在Vue中,利用Vue Router可以灵活地构建既拥有SPA即时响应特性的部分,也包含传统页面导航结构的多页应用,平衡用户体验与搜索引擎优化的需求。

10.1.4、多页应用程序应用场景


1. 公司官方网站:强调信息展示、品牌宣传的公司官网,MPA通过独立页面有效优化SEO,确保每个页面都能被搜索引擎有效抓取,增加网络可见度。

2. 电子商务平台:电商类网站因涉及大量产品列表、分类浏览、详情展示等页面,且对SEO有较高要求,MPA通过清晰的页面结构和独立URL更好地支持这些需求,同时便于管理和追踪不同的访问路径。

10.1.3、单页应用和多页应用对比


选择SPA还是MPA架构需根据项目具体需求来定,如用户交互的深度、SEO的重要性、移动端兼容性等因素综合考虑,以达到最佳的用户体验和业务目标。


10.2、VueRouter路由

10.2.1、SPA提升用户体验的原理


SPA提升效率、性能与体验的关键,在于页面按需更新,减少不必要的页面刷新,实现快速响应与无缝交互,加之组件化开发加速迭代。


例如,点击“发现音乐”或“关注”时,仅下方内容动态变化,页面头部保持不变,实现了瞬时响应。

要实现瞬时响应就需要精确匹配URL路径与相应UI组件,这一过程可以通过路由系统巧妙实现,确保用户每一步操作都能精准激活所需模块,无冗余加载,保证了应用的敏捷与流畅。

10.2.2、路由介绍


生活中的路由:设备和ip的映射关系。




Vue中的路由:路径和组件的映射关系。


10.2.3、组件分类


.vue文件分为2类,都是.vue文件(本质无区别)

1.页面组件:配置路由规则时使用的组件;
2.复用组件:多个组件中都使用到的组件。


10.2.4、组件的存放目录


分类开来的目的就是为了更易维护

1.src/views文件夹存放页面组件,页面展示,配合路由用。

2.src/components文件夹存放复用组件,展示数据,常用于复用。也有放在在页面组件的文件夹的子文件中的。

10.3、VueRouter基本使用

10.3.1、VueRouter路由的作用


VueRouter 的作用在于它能够无缝响应地址栏路径的更改,进而动态渲染与当前路径匹配的组件,无需刷新页面,为用户带来流畅的单页应用体验。

10.3.2、VueRouter路由的使用


使用VueCli脚手架创建项目时,勾选Router选项。


10.3.2、路由的封装抽离


随着应用规模的扩张,将全部路由配置嵌入main.js文件中可能引发维护难题,降低代码的可读性和可管理性。因此在实际开发中会将路由配置从main.js中抽离出来封装到一个.js文件文件中。


10.3.3、路由使用案例


脚手架环境下 @指代src目录,可以用于快速引入组件。


10.4、VueRouter提供的导航方式

VueRouter提供了两种主要的导航方式,分别是声明式导航和编程式导航。

10.4.1、声明式导航


声明式导航是通过在模板中使用特定的指令或组件来实现页面导航。在Vue中,主要使用<router-link>组件来创建导航链接。<router-link>组件类似于HTML中的<a>标签,但它专门用于Vue Router的路由链接。通过设置<router-link>的to属性,可以指定目标路由的路径或命名路由。



当点击这个链接时,Vue Router会自动处理路由的切换,并显示对应的目标页面。声明式导航的优点是简单直观,不需要编写额外的JavaScript代码。


10.4.2、编程式导航


编程式导航是通过在JavaScript代码中使用Vue Router提供的API来实现页面导航。与声明式导航不同,编程式导航是通过调用路由实例对象的API方法来实现路由的导航。

Vue Router提供了一个$router对象,它包含了多个方法用于编程式导航,如push、replace、go等。

push:向路由历史记录中添加一个新的记录,并跳转到该记录对应的路由。
replace:替换当前路由记录,并跳转到新的路由。 
go:在路由历史记录中前进或后退指定的步数。



这段代码会向路由历史记录中添加一个新的记录,并跳转到/search路由对应的页面。编程式导航在需要在JavaScript代码中动态地改变路由时非常有用。

10.4.3、两种导航方式总结


声明式导航和编程式导航是Vue Router提供的两种主要的导航方式。声明式导航简单直观,适用于在模板中直接创建导航链接的场景;而编程式导航则更加灵活,适用于在JavaScript代码中动态地改变路由的场景。

10.5、声明式导航介绍

10.5.1、导航链接需求



如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,会很麻烦。vue-router 提供了一个全局组件 router-link 取代 a 标签进行路由跳转。

语法:配置 to 属性指定路径,能高亮,默认就会提供高亮类名,可以直接设置高亮样式。



10.5.2、导航链接代码示例



10.5.3、声明式导航的两个类名


当我们使用<router-link></router-link>跳转时,自动给当前导航加了两个类名。




1.router-link-active:糊匹配。


to=“/my” 可以匹配 /my /my/a /my/b …


模糊匹配用得比较多,模糊匹配只要是以/my开头的路径都可以和 to="/my"来匹配到。




2.router-link-exact-active:精确匹配。


to=“/list” 仅可以匹配 /list路径。



10.6、声明式导航-路由传参

10.6.1、查询参数传参


1.查询参数传参:




2.接受参数:

在目标组件内,你可以通过this.$route.query对象来访问这些查询参数,固定用法如下:

// 访问查询参数const 参数值 = this.$route.query.参数名;

3.这种方式简便易用,适合传递非必要或非私密的数据,且不会影响URL的美观,因为参数直接体现在URL中,易于分享和记录。

10.6.2、动态路由传参


1.动态路由传参概述:动态路由是Vue Router中用于处理具有可变部分的URL的一种方式,这些可变部分通常用于表示某种资源的ID。动态路由参数通过在路由路径中使用冒号(:)包裹参数名来定义。



2.定义动态路由:在router/index.js或相应的路由配置文件中,定义动态路由路径,例如,一个文章详情页可能这样配置:




3.传递参数:动态路由的参数可以直接通过URL传递,无需额外编码。

例如导航到文章详情页时:


注意:当使用name和params进行导航时,确保路由定义中包含了:参数名来匹配动态参数。



4.接收参数:在目标组件,如ArticleDetail,内部,通过this.$route.params来访问动态路由参数:


10.6.3、路由页面传参策略


在Vue应用中,通过声明式导航实现页面跳转时,向路由页面传递参数主要有两种策略:查询参数传参和动态路由传参,它们各有特点,适用于不同的场景。



1.查询参数传参:


适用场景:适合传递多个非关键性参数或筛选条件,如分页信息、过滤条件等。
特点:参数通过URL的查询字符串形式附加,易于构造和分享链接,但URL可能显得冗长。

示例:





2.动态路由传参:


适用场景:主要针对每个页面或资源具有唯一标识符的情况,如用户ID、文章ID等。
特点:直接将参数嵌入到URL路径中,使URL结构更加清晰、语义化,对SEO友好,但通常限于单个主要参数。

示例:





3.总结:选择查询参数还是动态路由传参,取决于参数的性质和应用场景。查询参数适用于携带多个辅助信息的场景,而动态路由参数则更适合直接关联资源标识的导航。两者结合使用,可以灵活应对各种路由传参需求,提升应用的用户体验和可维护性。

10.7、编程式导航-path路径跳转传参

10.7.1、编程导航介绍


编程式导航是通过在JavaScript代码中使用Vue Router提供的API来实现页面导航。编程式导航有两种传参方式,分别是 path 路径跳转传参和 name 命名路由跳转传参。

10.7.2、path 路径跳转-query传参


1. 适用场景:当参数不是路由的一部分,而是作为额外信息传递时,可以使用query方式。这种方式的参数会显示在URL中,易于分享且对SEO更友好。



2. query查询参数传参语法格式:




3. 代码示例:


10.7.3、path 路径跳转-动态路由传参


1.适用场景:当参数是路由结构的一部分时,应使用动态路由params。这使得URL更加语义化,同时参数不会以查询字符串的形式暴露。




2. 代码示例

步骤1:定义动态路由:

在路由配置中定义一个带有冒号 : 的动态段:




步骤2:使用name属性或直接构造路径进行跳转:


步骤3:接收参数:

在目标组件中,通过this.$route.params来访问这些参数:




3.注意事项:


(1) Query与Params的区别:Query参数在URL的查询字符串中体现,而Params参数直接体现在URL的路径部分。Params传递需要预先在路由配置中定义动态路径。

(2Path与Params的限制:提到的“path不能配合params使用”是指直接使用this.$router.push('/路径')形式时,如果该路径是动态路由定义的,仅通过这种方式无法传递params,必须显式使用{ path: ..., params: ... }的形式来传递。

(3刷新问题:动态路由(params)传递的参数在页面刷新后可能会丢失,因为它们不会被浏览器记录为历史状态。如果需要持久化这些参数,可以考虑使用Vue Router的beforeRouteUpdate钩子或其他客户端存储方案(如localStorage)来处理。而query查询参数传参则不会遇到这个问题,因为它们始终存在于URL中。


10.8、name命名路由传参

在Vue应用中,通过编程式导航利用name命名路由进行参数传递是一种高效且易于维护的方式。


10.8.1、name 命名路由-query传参


1.name命名空间-query查询参数路由传参语法格式:




2.代码示例:

步骤1:在发起跳转的组件使用this.$router.push()传递参数。




步骤2:在目标组件通过this.$route.query.id接收参数。


10.8.2、name命名-动态路由传参


步骤1:定义动态路由。




步骤2:在发起跳转的组件使用this.$router.push()传递参数。





步骤3:接收参数:

在目标组件中,通过this.$route.params来访问这些参数:


10.9、路由重定向

10.8.1、重定向的需求


网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白。要解决的问题是当用户输入ip后,如果用户输入的url路径不对时,统一跳转到首页。


10.10、路由404

1.作用:当路径找不到匹配时,给个提示页面。

2.位置:404的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面。

3.语法:path: "*",*代表任意路径的意思,如果前面路径都没有匹配到,就命中最后这个。


10.11、二级路由配置

10.11.1、二级路由介绍


在Vue中,二级路由(也称为嵌套路由)允许你在一个路由的基础上进一步定义子路由。这在你想要构建一个具有多级导航的应用时非常有用。

10.11.2、配置二级路由


在Vue Router中,可以通过children属性来定义子路由。以下是一个简单的配置示例。


10.11.3、使用二级路由


在ParentComponent.vue父组件的模板中,需要使用<router-view>来渲染子路由对应的组件。这样,当子路由被匹配时,相应的组件就会被渲染到<router-view>所在的位置


10.11.4、项目实战


步骤1:配置二级路由。




步骤2:使用二级路由进行传参。


10.12、缓存组件


10.12.1、需求背景


从“面经列表”点到“详情页”,再点返回,数据重新加载回到列表顶部了。原因是路由被跳转时会执行组件内的beforeDestroy和destroyed生命周期钩子,原来所看到的组件就被销毁了,当重新返回时会执行组件内的beforeCreate,created,beforeMount,Mounted生命周期钩子组件又被重新创建了,所以数据会被加载初始化。

需求是望回到原来的列表位置,解决方案是利用keep-alive把原来的组件给缓存下来。


10.12.2、keep-alive介绍


keep-alive是Vue框架集成的一种高级组件技术,专门用于实现组件状态的持久化与高效复用。当它包裹其他动态组件时,扮演着组件缓存管理者的角色,能够自动地保存不处于活跃状态的组件实例,避免因页面切换而导致的实例销毁与重建,从而实现组件的瞬时切换以及回到上一次浏览的位置及状态。

keep-alive 是一个抽象组件:它自身不会参与DOM文档对象模型的构建和渲染,它的存在是隐式的,不会出现在父组件中。

10.12.3、keep-alive的优点


1. 在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM;
2. 减少加载时间及性能消耗,提高用户体验性。

10.12.4、keep-alive的三个属性


如果使用keep-alive直接包裹<router-view>标签,则他会缓存了所有被切换的一级路由组件。如果希望有的组件被缓存,有的不被缓存,就可以通过配置keep-alive的三个属性来实现。


①include:组件名数组,只有匹配的组件会被缓存;
②exclude:组件名数组,任何匹配的组件都不会被缓存;
③max:最多可以缓存多少组件实例。

10.12.5、缓存特定组件


使用include定义了缓存的组件名数组,只有匹配的组件会被缓存,写缓存那几个组件,就换成哪几个组件。

实现步骤:

步骤1:在路由配置中,通过meta字段标记哪些路由需要被keep-alive缓存。




步骤2:使用:include的数组里定义需要被缓存的组件。


10.12.6、排除特定组件缓存


使用 exclude 属性排除特定组件缓存如果我们想缓存所有组件,除了 "Login" 和 "Error" 页面,可以使用 exclude。


10.12.7、限制缓存组件数量


使用 max 属性限制缓存组件数量,若需限制缓存组件的最大数量,例如最多缓存5个组件实例。


10.12.8、keep-alive触发的生命周期


组件使用keep-alive被缓存了,组件中created、mounted和destroyed等函数里面的内容就不会被触发。



需求:用户回到首页,给予一个回到首页的提示语。



因为缓存了组件,所以组件内原本的created和mounted等函数就不会触发,所以keep-alive提供了activated和deactivated两个函数。


activated: 当一个被<keep-alive>缓存的组件被重新激活并显示给用户时调用。这类似于组件的mounted钩子,但在组件已经被创建过的情况下触发。常用于数据的更新、重新绑定事件监听等。

deactivated: 当一个被缓存的组件从活跃状态变为非活跃状态时调用,即组件被隐藏但未被销毁时触发。类似于组件的beforeDestroy钩子,适合做清理工作,比如取消网络请求、清理定时器等,以避免内存泄漏。



代码示例:


10.12.9、keep-alive总结


1.keep-alive是Vue的内置组件,包裹动态组件时,可以缓存,通常配置路由一起使用。

2.默认路由切换组件时会将上一个组件销毁掉的,keep-alive的优点是组件切换过程中,把切换出去的组件保留在内存中,进而提示性能。

3.默认情况下,使用<keep-alive>包裹动态组件,会将所有一级组件都换成了,如果只希望缓存某些组件,就可以通过keep-alive提供的属性来缓存,一般会将include和max结合使用。

4.使用keep-alive会触发activated和deactivated这两个函数。

10.12、页面开发步骤总结

1. 先配置路由,再完成具体页面内容;
2. 嵌套路由的关键配置项是chidren;
3. 路由传参方式有查询参数和动态路由传参这两种;
4.缓存组件可以用到keep-alive这个内置组件。


第 11 章

ESLint代码规范


11.1、代码规范

11.1.1、代码规范介绍


1. 代码规范:一套写代码的约定规则。


2. ESLint介绍是一个代码检查工具,用来检查代码是否符合指定的规则

3. JavaScript Standard Style 规范网址:

https://standardjs.com/readme-zhcn.html。



11.1.2、代码规范示例


1. 字符串使用单引号,需要转义的地方除外;

2. 代码后面不用写分号;

3. 空格与括号: 在if, for, while等关键字之后应添加一个空格,同样地,在函数声明、调用以及对象字面量的花括号前也应加空格,例如:


4. 坚持使用全等 ===,摒弃 ==,当需要需要检査 null和undefined 时可以使用 obj == nu11;


5. 对象属性: 对象字面量中,键与值之间使用冒号加一个空格分隔,多个键值对之间以逗号分隔,并在最后一个键值对后也放置一个逗号,便于将来添加或修改属性。

6. 变量声明: 使用let和const代替var进行变量声明,以提升代码的块级作用域理解和避免变量提升的问题。



7.  箭头函数: 当函数体简单时,推荐使用箭头函数以简化语法,但注意这会影响this的绑定。



8. 模板字符串: 对于多行字符串或需要插值的字符串,使用模板字符串(反引号)而非字符串连接。


……


11.1.3、代码规范错误演示


如果你的代码不符合standard的要求,eslint会跳出来刀子嘴,豆腐心地提示你。

下面我们在main.js中随意做一些改动:添加一些空行,空格,保存代码之后,将会看在控制台中输出如下错误:


11.1.4、手动修复代码错误


手动代码修复:根据错误提示来一项一项手动修正,如果不认识命令行中的语法报错什么意思,可以根据错误代码描述去ESLint规则列表中查找具体含义。

ESLint规则表网址:
https://zh-hans.eslint.org/docs


11.2、通过ESLint自动修复代码

11.2.1、安装ESLint


步骤1:全局安装ESLint。

npm install -g eslint

步骤2:项目中配置ESLint,在项目根目录下初始化ESLint配置文件。可以通过运行以下命令来生成一个.eslintrc.*配置文件,如 .eslintrc.json,并根据提示选择或自定义规则。

11.2.2、IDEA配置ESLint


步骤1:安装ESLint插件。


步骤2:启用ESLint检查,配置ESLint工作方式,自动修正代码,你可以将鼠标悬停在警告上查看具体信息,或者直接按下Alt + Enter来查看并应用快速修复建议,其中包括自动修正代码的选项。


第 12 章

前端缓存


12.1、前端缓存介绍

前端缓存是Web开发中一种重要的性能优化策略,旨在通过减少网络请求,加快页面加载速度,提升用户体验。前端缓存主要分为以下几种类型:浏览器缓存、HTTP缓存、以及Web存储,如SessionStorage和LocalStorage。这些技术各有特点,适用于不同的场景,共同为提升网站性能服务。


12.2、SessionStorage会话缓存

12.2.1、sessionStorage介绍


SessionStorage提供了在单个浏览器窗口或标签页中持久化数据的能力,数据仅在同一个会话期间有效,当用户关闭浏览器窗口或标签页时,数据会被清除。这对于存储不敏感的临时数据非常有用,比如表单输入状态。

12.2.2、SessionStorage常用API


setItem:存储数据;
getItem:获取数据;
removeItem:删除数据;
clear:清空整个SessionStorage。


12.2.2、封装SessionStorage对象



12.2.3、存储数据



12.2.4、获取存储的数据



12.3、LocalStorage本地缓存

12.3.1、LocalStorage介绍


LocalStorage则提供了更为持久化的数据存储方案,即使在浏览器关闭后,数据依然存在,直到用户主动清除浏览器数据或通过代码删除。它适合存储用户偏好设置、认证令牌等不需要频繁更新且不涉及隐私的信息。

12.3.2、LocalStorage常用API


setItem:存储数据;
getItem:获取数据;
removeItem:删除数据;
clear:清空整个LocalStorage。


12.3.3、封装LocalStorage对象



第 13 章

Vuex状态管理工具


13.1、Vuex概述


13.1.1、Vuex介绍


Vuex 是 Vue 项目中实现大范围数据共享的技术方案,并且共享的数据是“响应式” 的,数据的存取一步到位,不需要层层传递,即数据的变更能及时渲染到模板。与之对比 localStorage 与 sessionStorage 也能共享数据,但缺点是数据并非“响应式”。

13.1.2、状态管理介绍


状态管理就是把需要多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的 Vue 实例中,让其他组件可以使用,共享这个对象中的所有变量属性,并且是响应式的。

13.1.3、安装Vuex步骤



13.1.4、手动安装vuex


步骤1:使用yarn或者npm安装vuex。

yarn add vuex@3 或者 npm i vuex@3

步骤2:为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。


步骤3:创建仓库 store/index.js。


步骤4:在 main.js 中导入挂载到 Vue 实例上。


13.1.5、使用脚手架安装vuex


使用 vue-cli 工具创建项目,并且选择了Vuex功能,前面小节的配置已经存在了。

13.3、state公共数据源


13.3.1、state介绍


State是Vuex的核心概念之一,扮演着应用状态容器的角色。它提供了一个集中化的数据存储区,使得整个应用程序的状态能够得到统一管理。任何组件需要共享的数据都应该保存在State中,以此保证数据的一致性和可维护性。

13.3.2、提供数据


要在Vuex中提供共享数据,需要在项目的store模块里定义这些数据。通常,这涉及到在store的state对象中声明这些数据成员。。


13.3.3、访问数据


1. 通过$store直接访问:{{  $store.state.score }};
2. 通过辅助函数mapState 映射计算属性:{{ score  }}。


13.3.4、mapState辅助函数


mapState是辅助函数,帮助我们把store中的数据映射到组件的计算属性中, 它属于一种方便的用法。


上面代码的最终得到的是类似于下面的代码。



13.3.5、mapState辅助函数案例


步骤1:导入mapState ,mapState是vuex中的一个函数;
步骤2:采用数组形式引入state属性;
步骤3:在模板中直接使用插值表达式渲染计算属性中的值。



13.3.6、Vuex的单向数据流


vuex 同样遵循单向数据流,组件中不能直接修改仓库的数据。通过 strict: true 可以开启严格模式。开启严格模式后,直接修改state中的值会报错


state数据的修改只能通过mutations,并且mutations必须是同步的。


13.4、mutations

13.4.1、mutations介绍


mutations里面放的都是方法,这些方法的作用是更新 state 中存储的数据;就相当于javabean的set方法,通过mutations就可以给state里面的属性赋值以及修改数据。

13.4.2、定义mutations


mutations和 state 是平级的。


13.4.3、mutations案例示例


1. 在store里面定义属性和方法:


2. 在组件中调用方法,$store.commit是设置数据。


3. 获取存储的数据:


13.5、mapMutations辅助函数


13.5.1、mapMutations介绍


mapMutations 是 Vuex 提供的一个辅助函数,旨在简化组件中对 store 中 mutations 的调用过程,促进代码的整洁与易维护性。

通过 mapMutations,可以直接将 store 中的 mutations 方法映射到组件的 methods 上,无需每次调用时都手动书写 this.$store.commit。这种方式不仅减少了代码量,也提高了代码的可读性和可维护性。



上面代码的含义是将mutations的方法导入了methods中,等价于下面的代码。



13.5.2、mapMutations代码示例


需求:设计一个计数器应用,其中 mutations 负责更新计数状态。



store/index.js代码示例:





在组件中,利用 mapMutations 来简化调用。



13.6、Vuex中的双向绑定

13.6.1、需求描述


在组件的输入框实时输入,实时更新数据。


13.6.2、实现步骤



1. 初始化 Vuex Store: 在 Vuex 的 state 中定义要绑定的数值状态(如 count)。
2. 定义 Mutation: 创建一个用于更新该数值状态的 mutation 函数,接收新的数值作为参数。
3. 组件内绑定与处理: 在 Vue 组件中,使用 v-model 或 :value 配合 @input 事件模拟双向绑定效果,当 input 值发生变化时,触发方法调用 Vuex 的 mutation 更新状态。
4. 状态映射至组件: 可选地,使用 mapState 辅助函数将 Vuex 状态映射到组件的计算属性,以便更简洁地在模板中使用状态。

13.6.3、index.js代码示例


store/index.js代码示例:


13.6.4、App.vue代码示例



13.7、actions异步操作

13.7.1、actions介绍


在 Vuex 中,actions 作为连接组件与 mutations 的桥梁,主要负责处理异步操作,如 API 调用、延时操作等。它不能直接修改状态,而是通过 commit 触发同步的 mutations 来间接更新状态,这样做的好处是使得状态变更行为更容易追踪和调试。


state是存放数据的;
mutations是同步更新数据,便于监测数据的变化, 更新视图等, 方便于调试工具查看变化;
actions则负责进行异步操作。


13.7.2、actions核心功能


异步操作:actions 支持异步操作,弥补了 mutations 必须同步的限制。
提交Mutation:完成异步处理后,通过 context.commit 触发一个或多个 mutations 来更新状态。
扩展功能:相比直接在组件中执行异步操作,使用 actions 可以更集中地管理异步逻辑,便于维护和测试。

13.7.3、actions工作流程



13.7.4、index.js代码示例



13.7.5、组件内调用actions



13.7.6、mapActions辅助函数


mapActions 是把位于 actions中的方法提取了出来,映射到组件methods中。



13.7、getters条件筛选

13.7.1、getters介绍


在 Vuex 中,getters 用于从 state 中派生出一些状态,即基于现有状态计算生成新的状态值。当我们需要从state中筛选出符合条件的一些数据,这些数据是依赖state的,此时会用到getters

13.7.2、getters应用案例


state中定义了list,为1-10的数组,组件中,需要显示所有大于5的数据,正常的方式,是需要list在组件中进行再一步的处理,但是getters可以帮助我们实现它。


13.7.3、store代码配置共享数据



13.7.3、组件内使用getters


1. 简洁的计算逻辑:在 getters 中直接定义筛选逻辑,保持数据处理的纯净性和逻辑的集中性。
2. 利用 mapGetters 辅助函数:简化组件中对 getters 的引用,使得组件代码更简洁,直接通过计算属性访问过滤后的数据。
3. 直接在模板中迭代:通过映射后的计算属性,可以在模板中直接遍历使用,无需手动调用 $store.getters,提高了模板的直观性和易读性。



13.7.4、mapGetter辅助函数补充



13.8、modules模块化设计

13.8.1、模块设计背景


使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。


13.8.2、模块定义-准备store


1. 创建两个独立的模块:user 和 setting。每个模块都包含自己的状态、mutations、actions、getters,以便于管理和维护特定领域的状态。export default导出默认接口时需要使用namepaced: true开启命名空间。



2. user 模块管理用户信息状态:




3. setting 模块管理应用设置状态:




4.在store/index.js文件中的modules配置项中,注册这两个模块:





5. 访问模块中状态:

(1) 直接访问: 通过模块路径访问模块内的状态,如 

$store.state.setting.theme

(2) 映射到组件: 利用 mapState 辅助函数,将模块内的状态映射到组件的计算属性中,使访问更为便捷。


13.8.3、获取模块内的mutations方法


1.直接通过模块名访问mutations中的方法。

$store.state.模块名.xxx示例:$store.state.user.userInfo.name

2.通过mapMutations映射:

1. 默认根级别的映射:mapMutations(['xxx']) 

2. 子模块的映射开启命名空间,设置namespaced:true后,可以通过mapMutations('模块名',['xxx'])访问mutations中的方法。



13.8.4、获取模块内的getters方法


modules/user.js:




Son1.vue 直接访问getters:




Son2.vue 通过命名空间访问getters


13.8.5、获取模块内的actions方法



默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。


1.直接通过store调用模块中actions的方法。

$store.dispatch('模块名.xxx',参数)

2.通过mapActions映射:

1. 默认根级别的映射:mapActions(['xxx']) 

2. 子模块的映射开启命名空间,设置namespaced:true后,可以通过mapActions('模块名',['xxx'])访问actions中的方法。


3. user.js代码实现:


4. 方法1:组件内直接通过store调用actions方法。



5. 方法2:通过mapActions映射调用actions方法。



13.9、Vuex本地持久化

13.9.1、需求背景


在Web应用中,尤其是单页应用(SPA),用户数据的持久化存储对于提供连续性的用户体验至关重要。然而,当页面刷新或用户关闭浏览器后重新打开时,存储在 Vuex 中的用户信息和认证 Token 等重要数据可能会丢失。为了防止这种情况发生,可以利用浏览器提供的本地存储机制,如 localStorage 或 sessionStorage,来实现数据的持久化存储。

13.9.2、vuex-persistedstate介绍


vuex-persistedstate 是一个流行的 Vuex 插件,它的主要功能是将 Vuex store 中的状态持久化到客户端的本地存储中(通常是 localStorage 或 sessionStorage),从而在页面刷新或关闭后重新打开时,可以恢复之前的状态。这对于需要在用户会话之间保持状态的应用来说是非常有用的,比如保存用户的偏好设置、认证状态、购物车商品等。

13.9.3、安装vuex-persistedstate


npm install vuex-persistedstate --save

13.9.4、代码示例



13.9.5、登录成功后存储用户信息



第 14 章

AJAX


14.1、AJAX

14.1.1、AJAX介绍


Ajax: 全称Asynchronous JavaScript And XML,异步的JavaScript和XML,具体介绍:
[1] 与服务器进行数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。
[2] 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。

14.2、交互方式

14.2.1、同步交互


同步:没收到服务器返回数据,不能干别的。


14.2.2、异步交互


异步:请求发出去,还可以干别的,发起别的请求,服务器返回数据的时候,页面不会重写刷新,总的说来Ajax的异步可以允许前端页面在不重新加载整个页面的情况下完成与后台服务器的数据交换,让用户在无感知的情况下完成网页的局部内容刷新。这样就可以提升页面的加载速度,提供用户体验高。


14.2、axios

14.2.1、axios介绍


Axios是一个基于Promise的HTTP客户端库,它封装了原生的Ajax技术,提供了简洁易用的API来发起HTTP请求。通过Axios,开发者可以快速构建Web应用,实现前后端数据交互,提高开发效率。

14.2.2、项目中引入axios


步骤1:在项目的根目录下打开终端,然后输入以下命令来安装Axios:

npm install axios --save//或者yarn add axios



步骤2:在main.js中把axios依赖引进来。


14.2.3、统一配置域名ip


使用axios.defaults.baseURL定义域名ip,所有的请求都会带上它的值作为前置。



14.2.4、使用axios发起请求



14.3、封装请求方法

14.3.1、在api包下封装请求方法



14.3.2、页面调用api的方法发请求


步骤1:引入接口api




步骤2:

在JavaScript(特别是使用ES2017及更高版本的语法,也称为ES8或ESNext)中,async 和 await 是用于处理异步操作的关键字。它们使得异步代码看起来和同步代码一样,易于阅读和编写。


第 15 章

Vue+ElementUI实战


15.1、ElementUI

15.1.1、ElementUI介绍


ElementUI是一个基于Vue.js的开源UI组件库,由饿了么团队开发并维护。它提供了一套丰富的、优雅的、灵活的UI组件,帮助开发者快速构建美观且功能丰富的用户界面。



网址:https://element.eleme.cn/#/zh-CN/


15.1.2、项目中引入ElementUI


步骤1:在项目的根目录下打开终端,然后输入以下命令来安装ElementUI

npm i element-ui -S//或者cnpm install element-ui --save




步骤2:在main.js文件中全局引入ElementUI的依赖。


15.2、ElementUI常用组件

15.2.1、ElementUI的使用



15.2.2、ElementUI常用组件案例


1. el-button:按钮组件,用于触发操作或导航。




2. el-input:输入框组件,用于接收用户输入。




3. el-select:下拉选择器组件,用于从预设的选项中选择一个或多个值。




4. el-cascader:级联选择器组件,用于多层级数据的选择。




5. el-radio:单选框组件,用于在一组选项中选择一个值。




6. el-checkbox:复选框组件,用于在一组选项中选择多个值。




7. el-switch:开关选择器组件,用于表示两种状态之间的切换。




8. el-slider:滑块组件,用于在一定范围内选择值。




9. el-date-picker:日期选择器组件,用于选择日期或日期范围。




10. el-time-picker:时间选择器组件,用于选择时间。





11. el-color-picker:颜色选择器组件,用于选择颜色。




12. el-table:表格组件,用于展示数据列表。




13. el-tree:树形控件组件,用于展示层级结构的数据。




14. el-form:表单组件,用于构建表单页面。




15. el-form-item:表单项组件,用于包装表单元素,并设置验证规则。




16. el-dialog:对话框组件,用于弹出对话框以显示信息或进行操作。




17. el-tooltip:文字提示组件,用于在鼠标悬停时显示提示信息。




18. el-progress:进度条组件,用于显示任务的进度。




19. el-tag:标签组件,用于显示轻量级的分类或状态信息。




20. el-alert:警告框组件,用于显示警告信息或操作提示。


15.3、表格组件实战

15.3.1、前端代码



15.3.2、后端实体类



15.3.3、后端接口



15.4、分页搜索

15.4.1、前端代码



15.4.2、后端实体类



15.4.3、后端接口



15.5、级联选择

15.5.1、前端代码


级联选择器中选项的数据结构为:





15.5.2、后端实体类



15.5.3、后端接口



第 16 章

Vue+Echarts实战


16.1、Echarts介绍

16.1.1、Echarts介绍


Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。Echarts支持超过20种图表类型,包括柱状图、折线图、饼图、散点图、雷达图等,并且可以结合十几种不同的组件进行自由组合,以满足多样化的展示需求。

16.1.2、Echarts官网


https://echarts.apache.org/zh/index.html


16.2、项目引入Echarts

16.2.1、安装Echarts


npm install echarts --save# 或者yarn add echarts

16.2.2、全局引入Echarts



16.2.3、在vue中使用Echarts


需要用到echart的地方先设置一个div的id、宽高。可以在一个页面中引入多个数据报表模板,使用div进行位置的排版放置。




要在mounted生命周期函数中实例化Echarts对象,确保dom元素已经挂载到页面中。




const option = { }就是我们需要引进echart图表的代码;
xAxis:x轴是类目数据;
yAxis:y轴是数值;
series:系列列表,data里面的数据内容要跟xAxis的类目数据一一对应;type是图表类型,type : 'line'的图表类型是折线图。




在beforeDestroy函数中销毁图表实例,避免内存溢出。


16.3、Echarts常用图表类型

Echarts图表类型在series数组的type中配置。

16.3.1、折线图


折线图(Line Chart)常用于显示数据随时间变化的趋势。



16.3.2、


饼图(Pie Chart)常用于展示各部分所占总体的比例。



16.3.3、


散点图(Scatter Chart)常用于展示数据点之间的相关性。


16.3.4、


雷达图(Radar Chart)常用于展示多维度数据比较。


16.3.5、柱状图+折线图组合


柱状图+折线图组合(Bar + Line Combo)常用于同时展示两类数据趋势。


16.3.6、地图


地图(Map)常用于对地理信息进行可视化分析,使用时需要引入地图文件。


16.3.7、饼状环图


饼状环图(Polar/Rose Chart):环形分布展现数据比例。



16.3.8、热力图


热力图(Heatmap)常用于展示二维数据的密度分布。


16.3.9、漏斗图


漏斗图(Funnel Chart)常用于展现数据的逐层筛选过程。



16.3.10、仪表盘


仪表盘(Gauge Chart)常用于展示单一关键指标的状态。


16.3.11、图表类型总结


不管是哪种形式的图形,最本质的东西实际上是数据,它其实是对数据的一种可视化展示。

16.4、营业额统计实战

16.4.1、需求原型图


业务规则:

营业额指订单状态为已完成的订单金额合计;
基于可视化报表的折线图展示营业额数据,X轴为日期,Y轴为营业额;
根据时间选择区间,展示每天的营业额数据。


16.4.2、接口设计


具体返回数据一般由前端来决定,前端展示图表,图表展示对应数据是什么格式,是有固定的要求的。

所以说,后端需要去适应前端,它需要什么格式的数据,我们就给它返回什么格式的数据。


16.4.3、VO设计



16.4.4、Controller层设计


根据接口定义创建ReportController:


16.4.5、Service层设计


创建ReportService接口,声明getTurnover方法:




创建ReportServiceImpl实现类,实现getTurnover方法:


16.4.6、Mapper层设计


在OrderMapper接口声明sumByMap方法:




在OrderMapper.xml文件中编写动态SQL:



16.4.7、功能测试



16.5、用户统计实战

16.5.1、需求原型图


业务规则:

基于可视化报表的折线图展示用户数据,X轴为日期,Y轴为用户数;
根据时间选择区间,展示每天的用户总量和新增用户量数据。


16.5.2、接口设计



16.5.3、VO设计



16.5.4、Controller层设计


根据接口定义,在ReportController中创建userStatistics方法:


16.5.5、Service层设计


在ReportService接口中声明getUserStatistics方法:




在ReportServiceImpl实现类中实现getUserStatistics方法:




在ReportServiceImpl实现类中创建私有方法getUserCount:


16.5.6、Mapper层设计


在UserMapper接口中声明countByMap方法:




在UserMapper.xml文件中编写动态SQL:


16.5.7、功能测试



16.6、订单统计实战

16.6.1、需求原型图


业务规则:

有效订单指状态为 “已完成” 的订单;
基于可视化报表的折线图展示订单数据,X轴为日期,Y轴为订单数量;
根据时间选择区间,展示每天的订单总数和有效订单数;
展示所选时间区间内的有效订单数、总订单数、订单完成率,订单完成率 = 有效订单数 / 总订单数 * 100%。


16.6.2、接口设计



16.6.3、VO设计



16.6.4、Controller层设计


在ReportController中根据订单统计接口创建orderStatistics方法:


16.6.5、Service层设计


在ReportService接口中声明getOrderStatistics方法:




在ReportServiceImpl实现类中实现getOrderStatistics方法:




在ReportServiceImpl实现类中提供私有方法getOrderCount:


16.6.6、Mapper层设计


在OrderMapper接口中声明countByMap方法:




在OrderMapper.xml文件中编写动态SQL:


16.6.7、功能测试



16.7、销量排名Top10统计

16.7.1、需求原型图


业务规则:

根据时间选择区间,展示销量前10的商品(包括菜品和套餐);
基于可视化报表的柱状图降序展示商品销量;
此处的销量为商品销售的份数。


16.7.2、接口设计



16.7.3、VO设计



16.7.4、Controller层设计


在ReportController中根据销量排名接口创建top10方法:


16.7.5、Service层设计


在ReportService接口中声明getSalesTop10方法:




在ReportServiceImpl实现类中实现getSalesTop10方法:


16.7.6、Mapper层设计


在OrderMapper接口中声明getSalesTop10方法:




在OrderMapper.xml文件中编写动态SQL:


16.7.7、功能测试




第 17 章

作者介绍


吴灿锦,泰伯一百零一世孙,明朝开国名将安陆侯吴复的后代,毕业于吉林财经大学;


第九届中国国际“互联网+”创新创业大赛吉林省赛区金奖项目总负责;


第十三届“挑战杯”中国大学生创业计划大赛吉林省赛区特等奖,国家级铜奖项目总负责


2022年荣获吉林财经大学创业实践国家级立项第一名项目总负责


· 往期回顾 ·


“互联网+”金奖与“挑战杯”特等奖——青春的舞台,美好的回忆
大数据高并发系统架构实战方案
SpringCloud微服务架构实战手册——从入门到精通全攻略
优秀毕业设计示例——基于SpringCloud Alibaba微服务在线教育系统的设计与实现的路演答辩
RabbitMQ异步通信全攻略——API操作与性能调优实战
Redis核心API速览与实战应用手册
JDK核心API速查手册与实用指南
Java开发手册阅读心得——黄山版
SpringBoot项目常用注解的积累与代码的优化实践
Spring Framework——掌握核心注解,优化你的应用程序
工作中常用的Linux命令——以阿里云ECS服务器为例
Mysql数据库系统学习笔记


远方的音讯
梧桐长成凤凰至,人伴贤良品行高!
 最新文章