Vue3你真的熟悉吗?02-生命周期钩子

原题传送门

题目:

看到这个题,点击这个切换子组件的按钮,销毁Child组件之后,我们再次去点击会发现这个时候 count 还是一直往上累加的,那么这到底是为什么呢?

javascript 复制代码
onMounted(() => {
  timer.value = window.setInterval(() => {
    count.value++;
  }, 1000);
});
vue 复制代码
<template>
  <div>
    <Child v-if="visible" />
    <p>
      <button @click="toggle">Toggle Child Component</button>
    </p>
  </div>
</template>

可以看到上面就是 count 递增的核心语法,那么再来分析,为什么点击切换子组件,由于用 v-if 指令控制,组件已经销毁了,再渲染的时候不是从上次销毁的数字继续,而是更大的数字,这表明组件销毁后,count 仍然在增加,这显然不是我们要的一个效果。

分析:

凡事必有因,别急先让我们来看几个概念。

首先看到vue官方文档的生命周期一节,onMounted 表示组件挂载完之后执行。

再看到MDN文档对setInterval这个方法的介绍,setInterval,在一定的时间间隔内会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID值可用作 clearInterval() 方法的参数。那么这里的问题就是我们通过setInterval创建了一个定时器,却没有执行 clearInterval() 来停止它 。

最后看到我们的题目:

javascript 复制代码
// Child.vue
<script setup lang="ts">
import { onMounted, onUnmounted, inject } from "vue"

const timer = inject("timer")
const count = inject("count")

onMounted(() => {
  timer.value = window.setInterval(() => {
    count.value++
  }, 1000)
})


</script>

<template>
  <div>
    <p>
      Child Component: {{ count }}
    </p>
  </div>
</template>
javascript 复制代码
// App.vue
<script setup lang="ts">
import { ref, provide } from "vue"
import Child from "./Child.vue"

const visible = ref(true)
const timer = ref(null)
const count = ref(0)
provide("timer", timer)
provide("count", count)

function toggle() {
  visible.value = !visible.value
}
</script>

<template>
  <div>
    <Child v-if="visible" />
    <p>
      <button @click="toggle">
        Toggle Child Component
      </button>
    </p>
  </div>
</template>

每次我们点击切换按钮的时候,子组件的onMounted钩子触发,就会在一秒后新建一个定时器,当我们快速点击toggle按钮多次后发现,这个count值增加得更快了,这到底是为什么呢?这是因为子组件反复挂载和销毁,可能会引发计时器的累积问题。每次子组件挂载时,都会创建一个新的计时器并启动,但之前的计时器并没有被清除,这会导致多个定时器并行运行,自然这个count的值也就新增多次也就是更快了。

解决:

点击切换按钮后,子组件销毁,那么也就会触发 onUnmounted 事件,尝试把停止时间的逻辑放到这里看看。

javascript 复制代码
onUnmounted(() => {
  window.clearInterval(timer.value);
});

这里就是每次销毁组件的时候,同时销毁创建的定时器,再次切换按钮运行,发现是可行的,在销毁期间 count 就不会再新增了。

相关推荐
程序员黄同学1 小时前
请谈谈 Vue 中的 key 属性的重要性,如何确保列表项的唯一标识?
前端·javascript·vue.js
繁依Fanyi1 小时前
巧妙实现右键菜单功能,提升用户操作体验
开发语言·前端·javascript·vue.js·uni-app·harmonyos
web182854825121 小时前
nginx 部署前端vue项目
前端·vue.js·nginx
memorycx2 小时前
Vue02
前端·javascript·vue.js
bin91538 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云9 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
计算机-秋大田16 小时前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
禾苗种树17 小时前
在 Vue 3 中使用 ECharts 制作多 Y 轴折线图时,若希望 **Y 轴颜色自动匹配折线颜色**且无需手动干预,可以通过以下步骤实现:
前端·vue.js·echarts
小盼江18 小时前
水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 代码+开发文档+视频教程
vue.js·spring boot·ui
初遇你时动了情19 小时前
react module.scss 避免全局冲突类似vue中scoped
vue.js·react.js·scss