# 一.组件的生命周期

# 1.生命周期

Vue 的生命周期是指 Vue 实例从创建到销毁的整个过程中,按照特定的顺序执行的一系列钩子函数(也称为生命周期钩子)。这些钩子函数允许开发者在不同的阶段插入自定义的代码逻辑,以控制和管理 Vue 实例的行为。

生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段。

image-20230708111301662

# 2.生命周期函数

  • 创建阶段
  • 挂载阶段
  • 更新阶段
  • 卸载阶段

生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。

注意:生命周期强调的是时间段,生命周期函数强调的是时间点。

Vue.js 是一种流行的 JavaScript 框架,提供了一些生命周期钩子函数,允许您在 Vue 组件的不同阶段执行自定义逻辑。下面是 Vue.js 2.x 版本的生命周期函数列表:

  1. beforeCreate:在 Vue 实例初始化之后,数据观测 (data observation) 和事件配置 (event/watcher setup) 之前被调用。
  2. created:在 Vue 实例创建完成后立即调用,可以访问已创建的实例,但无法进行 DOM 操作。
  3. beforeMount:在 Vue 实例挂载到 DOM 之前被调用。
  4. mounted:在 Vue 实例挂载到 DOM 后调用,可以进行 DOM 操作。这是大多数初始化工作的最佳时机。
  5. beforeUpdate:在响应式数据更新时调用,但在 DOM 重新渲染之前调用。
  6. updated:在 DOM 重新渲染后调用,可以执行依赖于 DOM 的操作。
  7. activated:在使用 keep-alive 组件包裹的组件激活时调用。
  8. deactivated:在使用 keep-alive 组件包裹的组件停用时调用。
  9. beforeDestroy:在 Vue 实例销毁之前调用,可以执行一些清理操作。
  10. destroyed:在 Vue 实例销毁后调用,所有的事件监听器会被移除,所有的子实例也会被销毁。
  11. errorCaptured:当子组件抛出错误时调用,可以用于错误处理和日志记录。

除了上述生命周期钩子函数之外,Vue 3.x 版本还引入了一些新的生命周期函数:

  1. beforeUnmount:在 Vue 实例卸载之前被调用,类似于 beforeDestroy。
  2. unmounted:在 Vue 实例卸载后调用,类似于 destroyed。

这些生命周期函数允许您在 Vue 组件的不同阶段执行代码,以处理数据的初始化、DOM 操作、清理和其他自定义逻辑。请注意,Vue 3.x 版本中的 beforeMount 和 mounted 钩子函数在 2.x 版本中分别为 beforeMount 和 mounted。

# 3.官网流程图

image-20230708111434418

# 二.组件之间的数据共享

# 1.组件之间的关系

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

① 父子关系

② 兄弟关系

image-20230708120239392

# 2.父子数据共享

父子组件之间的数据共享

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

① 父 -> 子共享数据

② 子 -> 父共享数据

# 3.父到子的数据

父组件向子组件共享数据需要使用自定义属性。示例代码如下:

在 Vue 中,父组件向子组件传递数据可以使用自定义属性来实现。您可以通过在子组件上定义 props 属性来接收来自父组件的数据。

以下是一个简单的示例:

在父组件中,使用 v-bind 指令将数据传递给子组件的 props 属性:

<template>
  <div>
    <child-component :message="parentMessage"></child-component>
  </div>
</template>

<script>
import ChildComponent from "./ChildComponent.vue";

export default {
  components: {
    ChildComponent,
  },
  data() {
    return {
      parentMessage: "Hello from parent component",
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在子组件中,通过 props 属性接收来自父组件的数据:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: ["message"],
};
</script>
1
2
3
4
5
6
7
8
9
10
11

在上述示例中,父组件通过 v-bind 指令将parentMessage数据传递给子组件的message属性。子组件通过 props 属性声明message,然后就可以在子组件的模板中使用该属性。

注意:父组件向子组件传递的数据是单向的,子组件无法直接修改父组件的数据。如果需要修改父组件的数据,可以使用自定义事件或 Vuex 等状态管理工具来实现。

props写法:

image-20230708163316113

# 4.子到父的数据

子组件向父组件共享数据使用自定义事件。示例代码如下:

image-20230708163354894

在 Vue 中,子组件向父组件共享数据可以通过自定义事件来实现。以下是实现的基本步骤:

  1. 在父组件中定义一个数据属性或变量,用于接收子组件传递的数据。
  2. 在父组件中注册一个自定义事件,并定义一个方法来处理该事件。
  3. 在子组件中触发自定义事件,并将需要共享的数据作为事件的参数传递给父组件。

下面是一个简单的示例:

在父组件中:

<template>
  <div>
    <h2>父组件</h2>
    <p>接收到的数据:{{ sharedData }}</p>
    <child-component @custom-event="handleCustomEvent"></child-component>
  </div>
</template>

<script>
import ChildComponent from "./ChildComponent.vue";

export default {
  components: {
    ChildComponent,
  },
  data() {
    return {
      sharedData: "",
    };
  },
  methods: {
    handleCustomEvent(data) {
      this.sharedData = data;
    },
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在子组件中:

<template>
  <div>
    <h3>子组件</h3>
    <button @click="emitCustomEvent">传递数据给父组件</button>
  </div>
</template>

<script>
export default {
  methods: {
    emitCustomEvent() {
      const data = "这是要传递的数据";
      this.$emit("custom-event", data);
    },
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在上面的示例中,子组件中的按钮被点击时,触发了自定义事件custom-event,并将数据'这是要传递的数据'作为参数传递给父组件。

父组件中的handleCustomEvent方法接收到子组件传递的数据,并将其赋值给父组件的sharedData属性。父组件中的模板中可以直接使用sharedData来显示接收到的数据。

通过这种方式,子组件就可以将数据通过自定义事件的方式传递给父组件,实现数据的共享和交互。

# 5.兄弟数据共享

image-20230708165312791

在 Vue 2.x 中,如果要实现兄弟组件之间的数据共享,可以使用 EventBus(事件总线)作为一种简单而有效的方案。

EventBus 是一个 Vue 实例,可以用作中央事件管理器,用于在组件之间传递消息和共享数据。以下是使用 EventBus 进行兄弟组件之间数据共享的基本步骤:

  1. 创建一个 EventBus 实例,在 Vue 应用的某个地方,例如在 main.js 文件中:
// main.js
import Vue from "vue";

// 创建EventBus实例
export const eventBus = new Vue();
1
2
3
4
5
  1. 在发送数据的组件中,通过 EventBus 实例触发事件,并传递数据:
// ComponentA.vue
import { eventBus } from "./main.js";

export default {
  methods: {
    sendDataToSibling() {
      const data = "这是要共享的数据";
      eventBus.$emit("custom-event", data);
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
  1. 在接收数据的组件中,通过 EventBus 实例监听事件,并在事件处理程序中获取共享的数据:
// ComponentB.vue
import { eventBus } from "./main.js";

export default {
  data() {
    return {
      sharedData: "",
    };
  },
  mounted() {
    eventBus.$on("custom-event", this.handleCustomEvent);
  },
  beforeDestroy() {
    eventBus.$off("custom-event", this.handleCustomEvent);
  },
  methods: {
    handleCustomEvent(data) {
      this.sharedData = data;
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在上面的示例中,ComponentA 组件通过eventBus.$emit方法触发了名为custom-event的事件,并传递了数据。ComponentB 组件通过eventBus.$on方法监听了custom-event事件,并在事件处理程序handleCustomEvent中获取到共享的数据并更新组件的sharedData属性。

通过 EventBus,兄弟组件之间可以进行数据的传递和共享,实现解耦和灵活的通信机制。但是需要注意,过度使用 EventBus 可能导致代码维护上的困难和混乱,因此在设计 Vue 应用时,需要慎重考虑使用 EventBus 的场景和频率。

# 6.EventBus 的使用步骤

① 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象

② 在数据发送方,调用 bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件

③ 在数据接收方,调用 bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件

# 7.总结

image-20230708112343501

# 三.ref 引用

# 1.什么是 ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用。每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象。

image-20230708165928684

# 2.使用 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:

image-20230708165956526

# 3.使用 ref 引用组件实例

如果想要使用 ref 引用页面上的组件实例,则可以按照如下的方式进行操作:

image-20230708170049639

# 4.控制文本框和按钮的按需切换

通过布尔值 inputVisible 来控制组件中的文本框与按钮的按需切换。示例代码如下:

image-20230708170140571

# 5.让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的

.focus() 方法即可。示例代码如下:

image-20230708170225265

# 6.this.$nextTick(cb) 方法

组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的

DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

image-20230708170258477

# 四.数组函数使用

# 1.数组的 somo 方法

在 Vue.js 中,你可以使用 some 方法来检查数组中的元素是否满足某个条件。some 方法会遍历数组中的每个元素,如果有任何一个元素满足条件,则返回 true,否则返回 false

下面是在 Vue.js 中使用 some 方法的示例:

<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
    <p v-if="hasSpecialItem">数组中存在特殊项。</p>
    <p v-else>数组中不存在特殊项。</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: "Item 1" },
        { id: 2, name: "Item 2" },
        { id: 3, name: "Special Item" },
        { id: 4, name: "Item 4" },
      ],
    };
  },
  computed: {
    hasSpecialItem() {
      return this.items.some((item) => item.name === "Special Item");
    },
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

在上面的示例中,我们有一个名为 numbers 的数组,然后在计算属性 hasEvenNumber 中使用了 some 方法来检查数组中是否存在偶数。如果数组中有任何一个元素满足 number % 2 === 0 这个条件,那么 hasEvenNumber 的值就为 true,否则为 false

你可以在 Vue.js 的计算属性、方法或生命周期钩子中使用 some 方法,具体取决于你的需求。只要将要处理的数组放在 Vue 组件的 data 选项中,就可以在组件的其他地方使用 some 方法来检查数组中的元素了。

# 2.数组的 every 方法

非常抱歉之前的回答有误。在 JavaScript 中,确实存在 every 方法用于检查数组中的所有元素是否都满足指定的条件。

以下是在 Vue.js 中使用 every 方法的示例:

data() {
  return {
    numbers: [1, 2, 3, 4, 5]
  };
},
computed: {
  allEven() {
    return this.numbers.every(number => number % 2 === 0);
  }
}
1
2
3
4
5
6
7
8
9
10

在上述示例中,我们有一个名为 numbers 的数组,并在计算属性 allEven 中使用了 every 方法来检查数组中的所有元素是否都是偶数。如果数组中的所有元素都满足 number % 2 === 0 这个条件,那么 allEven 的值就为 true,否则为 false

请注意,every 方法是 JavaScript 数组的方法,Vue.js 并未提供 every 方法。在 Vue.js 中,你可以在计算属性、方法或生命周期钩子中使用 JavaScript 数组的方法来操作和处理数组。

# 3.数组的 reduce 方法

在 Vue.js 中,你可以使用 reduce 方法来对数组进行累积计算。reduce 方法接受一个回调函数和一个初始值作为参数,然后将数组中的每个元素依次传入回调函数进行计算,并返回最终的累积结果。

以下是在 Vue.js 中使用 reduce 方法的示例:

data() {
  return {
    numbers: [1, 2, 3, 4, 5]
  };
},
computed: {
  sum() {
    return this.numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
  }
}
1
2
3
4
5
6
7
8
9
10

在上面的示例中,我们有一个名为 numbers 的数组,并在计算属性 sum 中使用了 reduce 方法来计算数组元素的总和。回调函数接受两个参数 accumulatorcurrentValue,分别表示累积值和当前值。初始值为 0。在每次迭代中,回调函数将累积值和当前值相加,并将结果作为下一次迭代的累积值。最终,sum 的值将是数组中所有元素的总和。

你可以根据需求自定义回调函数的逻辑来进行不同的累积计算。reduce 方法还可以接受第二个可选参数,用于指定回调函数的初始值。

需要注意的是,reduce 方法是 JavaScript 数组的方法,不是 Vue.js 提供的特定功能。在 Vue.js 中,你可以在计算属性、方法或生命周期钩子中使用普通的 JavaScript 数组方法,以对数组进行操作和处理。

# 4.数组的 forEach 方法

forEach 是 JavaScript 中 Array 类型的一个方法,用于迭代数组的每个元素并执行指定的操作。它提供了一种简洁的方式来遍历数组,而无需使用传统的 for 循环。

forEach 方法接受一个回调函数作为参数,该回调函数会在数组的每个元素上被调用一次,可以通过回调函数来对每个元素进行处理或执行其他操作。回调函数接受三个参数:当前元素的值、当前元素的索引和被遍历的数组本身。

以下是 forEach 方法的语法:

array.forEach(callback(currentValue, index, array))
1

其中,array 是要遍历的数组,callback 是回调函数。

下面是一个示例,展示如何使用 forEach 遍历数组并打印每个元素的值:

const array = [1, 2, 3, 4, 5];
array.forEach(function(element) {
  console.log(element);
});
1
2
3
4

在回调函数中,我们可以对每个元素进行自定义操作。例如,我们可以计算数组中所有元素的总和:

const array = [1, 2, 3, 4, 5];
let sum = 0;
array.forEach(function(element) {
  sum += element;
});
console.log(sum); // 输出 15
1
2
3
4
5
6

需要注意的是,forEach 方法没有返回值,它仅用于迭代数组中的每个元素。如果想要返回一个新的数组,可以考虑使用其他方法,如 map。另外,由于 forEach 方法无法中断循环,因此在需要中断或提前终止循环的情况下,可能需要使用传统的 for 循环或其他迭代方法。

使用Lambda表达式:

const array = [1, 2, 3, 4, 5];

// 使用 forEach 和 Lambda 表达式遍历数组
array.forEach((element) => {
  console.log(element);
});
1
2
3
4
5
6

# 五.购物车案例

# 1.实现步骤

① 初始化项目基本结构

② 封装 MyHeader 组件

③ 基于 axios 请求商品列表数据( GET 请求,地址为 https://www.escook.cn/api/cart )

④ 封装 MyFooter 组件

⑤ 封装 MyGoods 组件

⑥ 封装 MyCounter 组件

# 2.总结

① 能够知道 vue 中常用的生命周期函数

  •  创建阶段、运行阶段、销毁阶段
  •  created、mounted

② 能够知道如何实现组件之间的数据共享

  • 父 -> 子(自定义属性)
  • 子 -> 父(自定义事件)
  • 兄弟组件(EventBus)

③ 能够知道如何使用 ref 引用 DOM 元素或组件

  • 给元素或组件添加 ref="xxx" 的引用名称
  • 通过 this.$refs.xxx 获取元素或组件的实例
  • $nextTick() 函数的执行时机

# 3.指令顺序

  • 先指令
  • 再属性
  • 最后事件

image-20230709105707742

# 4.子向祖父传数据

使用 Event Bus 是一种在 Vue.js 中实现子组件向多级父组件传递数据的方法。Event Bus 是一个中央事件管理器,允许组件之间进行解耦的通信。以下是使用 Event Bus 实现子组件向多级父组件传递数据的步骤:

  1. 创建一个全局的 Event Bus 实例,通常可以在 main.js 中创建:
// main.js
import Vue from "vue";

export const eventBus = new Vue();
1
2
3
4
  1. 在需要传递数据的子组件中,使用 Event Bus 的 $emit 方法触发一个自定义事件,并将数据作为参数传递给该事件:
// ChildComponent.vue
import { eventBus } from "@/main.js";

export default {
  methods: {
    sendDataToParent() {
      const data = "Hello from child";
      eventBus.$emit("data-to-parent", data);
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
  1. 在多级父组件中,使用 Event Bus 的 $on 方法监听子组件触发的自定义事件,并在回调函数中处理传递的数据:
// ParentComponent.vue
import { eventBus } from "@/main.js";

export default {
  created() {
    eventBus.$on("data-to-parent", this.handleDataFromChild);
  },
  methods: {
    handleDataFromChild(data) {
      // 处理从子组件传递的数据
      console.log(data);
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在上述代码中,子组件使用 eventBus.$emit('data-to-parent', data) 触发了一个名为 data-to-parent 的自定义事件,并将数据 data 传递给该事件。多级父组件使用 eventBus.$on('data-to-parent', this.handleDataFromChild) 监听子组件触发的事件,并在 handleDataFromChild 方法中处理传递的数据。

通过 Event Bus,子组件可以向多级父组件传递数据,实现了跨层级的组件通信。需要注意的是,在适当的时机(如组件销毁)应该使用 eventBus.$off 方法取消事件监听,避免内存泄漏。

# 5.属性传递不封装

如果封装成一个对象,会在使用的地方,不知道对应的是哪个具体的字段,因为可能有多个对应一个

image-20230709112158689

上次更新: 10/29/2024, 10:27:50 AM