(五)组件高级(上)

watch 侦听器

1.什么是 watch 侦听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。例如,监视用户名的变化并发起请求,判断用户名是否可用。

2. watch 侦听器的基本语法

开发者需要在 watch 节点下,定义自己的侦听器。实例代码如下︰

image-20220428123323770

3.使用 watch 检测用户名是否可用

监听 username 值的变化,并使用 axios 发起 Ajax 请求,检测当前输入的用户名是否可用

image-20220428123350423

4.immediate 选项

默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。实例代码如下:

image-20220428123417857

5.deep 选项

当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项,代码示例如下:

image-20220428123438518

6.监听对象单个属性的变化

如果只想监听对象中单个属性的变化,则可以按照如下的方式定义 watch 侦听器:

image-20220428123458924

7.计算属性 vs 侦听器

计算属性和侦听器侧重的应用场景不同:
计算属性侧重于监听多个值的变化,最终计算并返回一个新值
侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值

组件的生命周期

1.组件运行的过程

image-20220428123548071

组件的生命周期指的是:组件从创建-→>运行(渲染)->销毁的整个过程,强调的是一个时间段。

2. 如何监听组件的不同时刻

vue 框架为组件内置了不同时刻的生命周期函数,生命周期函数会伴随着组件的运行而自动调用。例如:

  1. 当组件在内存中被创建完毕之后,会自动调用 created 函数

  2. 当组件被成功的渲染到页面上之后,会自动调用 mounted 函数

  3. 当组件被销毁完毕之后,会自动调用 unmounted 函数

3。如何监听组件的更新

当组件的 data 数据更新之后,vue 会自动重新渲染组件的 DOM 结构从而保证 View 视图展示的数据和 Model 数据源保持一致。
当组件被重新渲染完毕之后,会自动调用 updated 生命周期函数。

4.组件中主要的生命周期函数

生命周期函数 执行机制 所属阶段 执行次数 应用场景
created 组件在内存中创建完毕后 创建阶段 唯一 1 次 发 ajax 请求初始数据
mounted 组件初次在页面中渲染完毕后 创建阶段 唯一 1 次 操作 DOM 元素
updated 组件在页面中被重新渲染完毕后 运行阶段 0 或多次 -
unmounted 组件被销毁后(页面和内存) 销毁阶段 唯一 1 次 -

注意:在实际开发中,created 是最常用的生命周期函数!

5.组件中全部的生命周期函数

生命周期函数 执行机制 所属阶段 执行次数 应用场景
beforeCreated 在内存中开始创建组件之前 创建阶段 唯一 1 次 -
created 组件在内存中创建完毕后 创建阶段 唯一 1 次 发 ajax 请求初始数据
beforeMount 在把组件初次渲染到页面之前 创建阶段 唯一 1 次
mounted 组件初次在页面中渲染完毕后 创建阶段 唯一 1 次 操作 DOM 元素
beforeUpdate 在组件被重新渲染之前 运行阶段 0 或多次 -
updated 组件在页面中被重新渲染完毕后 运行阶段 0 或多次 -
beforeUnmount 在组件被销毁之前 销毁阶段 唯一 1 次 -
unmounted 组件被销毁后(页面和内存) 销毁阶段 唯一 1 次 -

疑问:为什么不在 beforeCreate 中发 ajax 请求初始数据?

请求的初始数据无法存储到 data 数据里,因为组件还未被创建

6.完整的生命周期图示

可以参考 vue 官方文档给出的“生命周期图示”,进一步理解组件生命周期执行的过程:

https://www.vue3js.cn/docs/zh/guide/instance.html#生命周期图示

组件之间的数据共享

1.组件之间的关系

在项目开发中,组件之间的关系分为如下 3 种:

  1. 父子关系

  2. 兄弟关系

  3. 后代关系

image-20220428124834698

2.父子组件之间的数据共享

父子组件之间的数据共享又分为:

① 父-→>子 共享数据
② 子->父 共享数据
③ 父<->子 双向数据同步

2.1 父组件向子组件共享数据

父组件通过 v-bind 属性绑定向子组件共享数据。同时,子组件需要使用 props 接收数据。示例代码如下:

image-20220428124925813

2.2 子组件向父组件共享数据

子组件通过自定义事件的方式向父组件共享数据。示例代码如下:

image-20220428124943381

2.3 父子组件之间数据的双向同步

父组件在使用子组件期间,可以使用 v-model 指令维护组件内外数据的双向同步:

image-20220428125001028

3.兄弟组件之间的数据共享

兄弟组件之间实现数据共享的方案是 EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实现兄弟组件之间的数据共享。示意图如下:

image-20220428125025788

3.1 安装 mitt 依赖包

在项目中运行如下的命令,安装 mitt 依赖包:

image-20220428125044418

3.2 创建公共的 EventBus 模块

在项目中创建公共的 eventBus 模块如下:

image-20220428125102716

3.3 在数据接收方自定义事件

在数据接收方,调用bus.on('事件名称'事件处理函数)方法注册一个自定义事件。示例代码如下:

image-20220428125136435

3.4 在数据接发送方触发事件

在数据发送方,调用bus.emit('事件名称',要发送的数据)方法触发自定义事件。示例代码如下:

image-20220428125203855

4.后代关系组件之间的数据共享

后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用 provide 和 inject 实现后代关系组件之间的数据共享。

image-20220428125232702

4.1 父节点通过 provide 共享数据

父节点的组件可以通过 provide 方法,对其子孙组件共享数据:

image-20220428125250097

4.2 子孙节点通过 inject 接收数据

子孙节点可以使用 inject 数组,接收父级节点向下共享的数据。示例代码如下:

image-20220428125314288

4.3 父节点对外共享响应式的数据

父节点使用 provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据。示例代码如下:

image-20220428125349801

4.4 子孙节点使用响应式的数据

如果父级节点共享的是响应式的数据,则子孙节点必须以.value 的形式进行使用。示例代码如下:

image-20220428125410756

5.vuex

vuex 是终极的组件之间的数据共享方案。在企业级的 vue 项目开发中,yuex 可以让组件之间的数据共享变得高效、清晰、且易于维护。

image-20220428125454202

6.总结

  • 父子关系

    1. 父->子 属性绑定
    2. 子>父 事件绑定
    3. 父<->子 组件上的 v-model
  • 兄弟关系

    1. EventBus
  • 后代关系

    1. provide & inject
  • 全局数据共享

  1. vuex

vue 3.x 中全局配置 axios

1.为什么要全局配置 axios

在实际项目开发中,几乎每个组件中都会用到 axios 发起数据请求。此时会遇到如下两个问题:

  1. 每个组件中都需要导入 axios(代码臃肿)
  2. 每次发请求都需要填写完整的请求路径(不利于后期的维护)

image-20220428125739760

2.如何全局配置 axios

在 main.js 入口文件中,通过 app.config.globalProperties 全局挂载 axios,示例代码如下:

image-20220428125802192

购物车案例

在 css 中,(+)是“相邻兄弟选择器”,表示:选择紧连着另一元素后的元素,二者具有相同的父元素。

1
2
3
4
5
6
7
8
9
.goods-container {
display: flex;
padding: 10px;
// 最终生成的选择器为 .goods-container + .goods-container
// 在 css 中,(+)是“相邻兄弟选择器”,表示:选择紧连着另一元素后的元素,二者具有相同的父元素。
+ .goods-container {
border-top: 1px solid #efefef;
}
}