vue 中监听生命周期事件

news2024/11/18 22:55:26

vue 中监听生命周期事件

    • 常见的添加自定义事件的写法
    • 希望在子组件挂载时通知父组件
    • 在模板上监听组件生命周期
    • vue3 生命周期事件吗?
      • jsx 中如何监听生命周期事件呢?
      • 通过 vNode 操作 html
    • vue3 父子组件的生命周期的执行顺序是怎样的?
    • 小结

vue2 提供了一些生命周期事件的方式,在组件销毁后触发一个事件,父组件可监听到该事件,然后执行某些操作。

命名为 hook:hookName ,前面的 hook: 是固定写法,比如 hook:mountedhook:beforeDestroy

常见的添加自定义事件的写法

{
  mounted() {
      this.onResize = () => {
        console.log('onResize')
      }
      window.addEventListener('resize', this.onResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.onResize)
    }
}

这种写法存在两个小问题:

  1. 添加了额外的变量onResize,感觉有点多余;
  2. 监听 resize 的逻辑分散在不同的生命周期中,不好维护。

使用监听生命周期事件的方式优化:

{

  mounted() {
    const onResize = () => {
      console.log('onResize')
    }
    window.addEventListener('resize', onResize)
    // hook:lifeHook $once 只执行一次
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', onResize)
    })
  }
}

凡在销毁时执行的操作,都可这样优化。

有人说方式1的问题不大,也没有优化多少,似乎没有多少用。

再看一个场景:

希望在子组件挂载时通知父组件

通常的写法:

// SonComponent.vue
{
  mounted() {
    this.$emit('mounted')
  }
}

在父组件中监听子组件触发的事件:

<template>
  <div>
    <SonComponent @mounted="onMounted" />
  </div>
</template>

<script>
  export default {
    methods: {
      onMounted() {
        console.log('onMounted')
      }
    }
  }
</script>

问题解决了,但是 SonComponent 是自己写的组件,具有完全的控制权,如果是第三方组件呢?

上面的方法就无招了。

生命周期事件可以解决这个问题:

在模板上监听组件生命周期

<template>
  <el-input @hook:mounted="onMounted" @hook:beforeDestroy="onBeforeDestroy" />
</template>
<script>
  export default {
    methods: {
      onMounted() {
        console.log('el-input onMounted')
      },
      onBeforeDestroy() {
        console.log('el-input onBeforeDestroy')
      }
    }
  }
</script>

生命周期事件在监听第三方组件的生命周期时很有用。

vue3 生命周期事件吗?

vue3 提供了 vue:hookName 的写法,比如 vue:mountedvue:unmounted

<script setup>
  import {
    ref
  } from 'vue'

  const input = ref('')

  function whenMounted(params) {
    console.log('whenMounted')
    console.log(params)
  }

  function whenBeforeUnmount() {
    console.log('whenBeforeUnmount')
  }

  function whenUpdated() {
    console.log('whenUpdated')
  }
</script>

<template>
  <el-input v-model="input" @vue:mounted="whenMounted" @vue:beforeUnmount="whenBeforeUnmount" @vue:updated="whenUpdated" />
</template>

this.$oncethis.$on 不再支持,可使用第三方库解决。

这些生命周期事件抛出的数据是组件的 vNode 对象,通过它,可获取到 elpropsref 等组件的重要属性。

比如,可获取 el ,然后手动修改它,以达到某种目的。

jsx 中如何监听生命周期事件呢?

vue3 提供了 onVnodeHookName 方法,可以监听组件的生命周期事件。

onVnodeMountedonVnodeBeforeUnmountonVnodeUpdated 等。

export default function MyButton(props, { slots }) {
  function onVnodeMounted(vnode) {
    console.log('vnode mounted', vnode)
  }
  return (
    <button onVnodeMounted={onVnodeMounted}>
      {{
        default: () => slots.default?.() ?? '按钮',
      }}
    </button>
  )
}

在模板中也是能使用这些方法的,但是不推荐,使用 @vue:hook 更直观。

vue:hookonVnodeXXX 在 vue3 的文档中没有找到,说明这些 API 可能不稳定,不要频繁使用它们。

通过 vNode 操作 html

项目中 animate.css 和 element-plus 一起使用,animate 的 [disabled] 样式属性权重太高,导致 element-plus 分页有禁用样式。

animate.css和element-plus的样式冲突
可以在分页组件挂载和更新后移除 disabled 属性,使用 onVnodeMountedonVnodeUpdated 事件实现。

<ElPagination 
    onVnodeMounted={removePaginationDisabled} 
    onVnodeUpdated={removePaginationDisabled} />

removePaginationDisabled 的参数是一个 vNode 对象,可通过 el 属性拿到 html 模板,然后手动修改它。

vue3 父子组件的生命周期的执行顺序是怎样的?

通过两个组件,可以观察到:

<!-- Parent.vue -->
<script setup>
  import {
    onBeforeMount,
    onBeforeUnmount,
    onBeforeUpdate,
    onMounted,
    onUnmounted,
    onUpdated,
    ref,
  } from 'vue'

  import MyInput from './MyInput.vue'

  const myInput = ref('')

  function whenBeforeMount() {
    console.log('Son vue:beforeMount')
  }

  function whenMounted() {
    console.log('Son vue:mounted')
  }

  function whenBeforeUpdate() {
    console.log('Son vue:beforeUpdate')
  }

  function whenUpdated(vNode) {
    console.log('Son vue:updated')
    console.log(vNode)
  }

  function whenBeforeUnmount() {
    console.log('Son vue:beforeUnmount')
  }

  function whenUnmounted() {
    console.log('Son vue:unmounted')
  }

  console.log('Parent setup')

  onBeforeMount(() => {
    console.log('Parent onBeforeMount')
  })

  onMounted(() => {
    console.log('Parent onMounted')
  })
  onBeforeUpdate(() => {
    console.log('Parent onBeforeUpdate')
  })
  onUpdated(() => {
    console.log('Parent onUpdated')
  })
  onBeforeUnmount(() => {
    console.log('Parent onBeforeUnmount')
  })
  onUnmounted(() => {
    console.log('Parent onUnmounted')
  })
</script>

<template>
  <div class="init-options">
    <p>this is p tag {{ myInput }}</p>
    <MyInput v-model="myInput" @vue:beforeMount="whenBeforeMount" @vue:mounted="whenMounted" @vue:beforeUpdate="whenBeforeUpdate" @vue:updated="whenUpdated" @vue:beforeUnmount="whenBeforeUnmount" @vue:unmounted="whenUnmounted" />
  </div>
</template>

MyInput.vue 作为子组件:

<script setup>
  import {
    onBeforeMount,
    onBeforeUnmount,
    onBeforeUpdate,
    onMounted,
    onUnmounted,
    onUpdated,
    ref,
  } from 'vue'

  console.log('Son setup')
  const props = defineProps({
    modelValue: {
      type: String,
      default: '',
    },
  })

  const emits = defineEmits(['update:modelValue'])

  const input = ref(props.modelValue)

  onBeforeMount(() => {
    console.log('Son onBeforeMount')
  })
  onMounted(() => {
    console.log('Son onMounted')
  })

  onBeforeUpdate(() => {
    console.log('Son onBeforeUpdate')
  })

  onUpdated(() => {
    console.log('Son updated')
  })

  onBeforeUnmount(() => {
    console.log('Son onBeforeUnmount')
  })

  onUnmounted(() => {
    console.log('Son onUnmounted')
  })

  function onInput(e) {
    input.value = e.target.value
    emits('update:modelValue', e.target.value)
  }
</script>

<template>
  <div>
    <input :value="input" @input="onInput" />
    <p>{{ input }}</p>
  </div>
</template>

vue3 的父子生命周期执行顺序是:

组件挂载

parent setup
parent onBeforeMount
parent vue:beforeMount
   son setup
   son onBeforeMount
   son vue:beforeMount
   son onMounted
   son vue:mounted
parent onMounted
# 类似两个圈,或者洋葱模型
# 父组件挂载阶段先进入后挂载

挂载阶段

销毁

Parent onBeforeUnmount
   Son vue:beforeUnmount # !生命周期事件先触发
   Son onBeforeUnmount
   Son onUnmounted
   Son vue:unmounted # ! 生命周期事件后触发
Parent onUnmounted
# 也类似洋葱模型

销毁阶段

更新

Parent onBeforeUpdate
   Son onBeforeUpdate
   Son vue:beforeUpdate
   Son updated
   Son vue:updated
Parent onUpdated
# 也类似两个圈 父组件先进入更新阶段,后更新

更新阶段

规律:父子组件的生命周期执行顺序类似一个两个圈,setup beforeXXX 在前方,XXXed 在后方,子组件的圈在内部。

生命周期事件在相应的生命周期钩子执行后触发,但是 vue:beforeUnmount 先于 onBeforeUnmount 执行,这点特殊。

小结

  • vue2 监听生命周期事件的方式:@hook:hookName
  • vue3 的方式 @vue:hookName或者onVnodeHookName
  • vue3 的父子组件每个阶段的生命周期执行顺序是两个圈,setup onBeforeXXX 在前方,XXXed 在后方,子组件的圈在内部。
  • vue:hookName 在 vue3 的文档中没有找到,说明这些 API 可能不稳定,不要频繁使用它们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1867501.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Swift中的二分查找:全面指南

Swift中的二分查找&#xff1a;全面指南 简介 二分查找是计算机科学中的经典算法&#xff0c;被广泛用于在已排序的数组中高效地搜索目标值。与线性查找逐个检查每个元素不同&#xff0c;二分查找不断将搜索区间减半&#xff0c;因此在处理大数据集时要快得多。 在这篇博客中…

FairyGUI框架下unity发布微信小游戏问题记录

一、unity发布微信小游戏中文字体不显示 在unity中发布WebGl项目时&#xff0c;如果使用的是默认字体就会出现中文字体丢失现象。 这个是在unity中 这个是在微信开发者工具里面显示的 解决办法&#xff1a; 打开我的电脑 C:\Windows\Fonts 随便找一个文件结尾为.ttf的字体…

如何实现系统重装和还原?电脑重装系统的详细介绍(内附系统还原教程)

我们使用电脑办公时&#xff0c;如果出现卡顿、运行缓慢、蓝屏崩溃或病毒感染时&#xff0c;可以通过重装系统的方法来解决。但是电脑系统还原和系统重装都比较麻烦&#xff0c;很多电脑小白跟小编一样&#xff0c;无从下手。 系统重装&#xff1a;重装系统则是将电脑系统完全清…

化茧成蝶 | 继HuggingFace首家落地大模型具身智能场景

关于具身智能的起源 近年来&#xff0c;大语言模型&#xff08;LLMs&#xff09;的兴起给机器人领域带来了革命性的改变&#xff0c;大模型赋予了传统机器人理解和推理的能力&#xff0c;让具身智能这一概念再度出现在大众的视角中。OpenCSG 作为国内 AI 开源社区的先锋&#…

如何快速解决验证码图像问题 | 最佳图像(OCR)验证码解决工具

你是否曾经遇到过陷入一个看似无尽的 CAPTCHA 挑战中&#xff0c;努力识别扭曲的字符或数字&#xff1f;这些令人抓狂的 CAPTCHA 是为了确保你是人类而不是机器人&#xff0c;但它们也给真正的用户带来了头痛。那么&#xff0c;有没有快速解决这些 CAPTCHA 图像的方法&#xff…

Python jsonschema库:数据验证的强大工具

更多Python学习内容&#xff1a;ipengtao.com 在处理JSON数据时&#xff0c;验证其结构和内容的正确性至关重要。jsonschema是一个用于描述和验证JSON文档结构的标准&#xff0c;Python的jsonschema库是实现这一标准的强大工具。本文将详细介绍jsonschema库的功能、安装与配置、…

安卓webview加载vue打包后的项目

<?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"ty.sql.dqwgsw"><uses-permission android:name"android.permission.INTERNET" /&g…

需求之 实现获取调试信息在h5页面,在手机端可以查看调试(二)

事实证明 chatgpt很好用&#xff0c;有不懂的问题可以问它 https://zhuanlan.zhihu.com/p/690118775 国内外9个免费的ChatGPT网站 我筛选出来的比较好用免费的网站 fchat.dykyzdh.cn/ 这个也可以 阿里云的 通义灵码 在vscode中安装使用 而且阿里云有一个产品&#xff0c;可以…

国产音频放大器工作原理以及应用领域

音频放大器是在产生声音的输出元件上重建输入的音频信号的设备&#xff0c;其重建的信号音量和功率级都要理想&#xff1a;如实、有效且失真低。音频范围为约20Hz&#xff5e;20000Hz&#xff0c;因此放大器在此范围内必须有良好的频率响应&#xff08;驱动频带受限的扬声器时要…

STM32F1+HAL库+FreeTOTS学习1——FreeRTOS入门

STM32F1HAL库FreeTOTS学习1——FreeRTOS入门 裸机开发与操作系统嵌入式操作系统简介FreeRTOS简介FreeRTOS的几个重要概念任务调度器任务状态状态列表 裸机开发与操作系统 在以往的嵌入式学习中&#xff0c;我们最常用的就是裸机开发&#xff0c;所谓裸机开发就是指在没有操作系…

AI开发Windows环境搭建

文章目录 1. GPU 支持检查2. 安装 Anaconda3. 创建 PyTorch 虚拟环境3.2 创建虚拟 PyTorchEnv 环境3.3 检查、激活、推出虚拟环境3.4 虚拟环境中python包管理3.5 虚拟环境中安装 PyTorch 框架 4. TensorFlow 安装 1. GPU 支持检查 打开 Task Manager (任务管理器&#xff09;&…

使用VMware创建Ubuntu 24.04【一】

相关链接下载地址 VMware https://www.vmware.com/content/vmware/vmware-published-sites/cn/products/workstation-pro/workstation-pro-evaluation.html.html.html Ubuntu 24.04 LTS https://cn.ubuntu.com/download/desktop 虚拟机创建 1、打开VNware软件&#xff0c;点…

Qt小项目 | 实现迅雷设置界面

文章目录 一、手写代码实现迅雷设置界面 一、手写代码实现迅雷设置界面 使用Qt控件&#xff08;如&#xff1a;QListWidget与QScrollArea等&#xff09;与布局实现腾讯会议登陆界面。设置界面除基本设置界面外&#xff0c;其他界面都是以图片的形式嵌入到项目中并没有手写代码。…

Mac 如何安装 wget

1.安装 Homebrew2.安装 wget3.检测 wget 是否安装成功 1.安装 Homebrew 在安装 wget 之前需要安装一个适用于 mac 的包管理器 Homebrew&#xff0c;打开 mac 终端执行如下命令进行安装&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/h…

DDD学习笔记二

模型的要素——用例、视图和构造块 模型的构建步骤 1&#xff09;从用例场景开始&#xff0c;给模型输入概念、属性、术语。 2&#xff09;构建静态领域模型&#xff08;类图&#xff09;&#xff0c;发现领域概念和对象属性。 3&#xff09;构建动态领域模型&#xff08;时序图…

自动化物流控制系统WCS应用与异常处理

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载 WCS的定义与作用&#xff1a; 物流仓储设备…

数据预处理功能教程,上传文件生成知识库 | Chatopera

如何快速的生成高质量的知识库&#xff1f; 数据预处理功能教程 | Chatopera 云服务低代码定制聊天机器人 关于 Chatopera Chatopera 云服务重新定义聊天机器人&#xff0c;https://bot.chatopera.com 定制智能客服、知识库、AI 助手、智慧家居等智能应用&#xff0c;释放创新…

【Java中导出Excel导出多个sheet页】

Java中导出Excel导出多个sheet页 序言如何处理多个sheet页的导出期间遇到了一个sheet页相关的问题&#xff0c;以及解决办法多sheet页导出遇到&#xff0c;第二个sheet页的标题名称会把第一个的覆盖的问题 结语 序言 在日常工作中经常有导出数据文件的需求&#xff0c;避免不了…

华为云鲲鹏架构docker部署2048小游戏

华为云鲲鹏架构docker部署2048小游戏 1. 鲲鹏架构ESC2. 配置docker3. 上传2048镜像4. 删除容器,镜像 1. 鲲鹏架构ESC 2. 配置docker 安装dockeryum -y install docker开机启动 systemctl enable docker启动docker服务 systemctl start docker查询docker的运行版本 docker -v3…

嵌入式linux系统中面试过程经验分享

大家好,今天主要给分享一下,如何在面试中介绍自己的项目经验,希望对大家有所帮助。 在面试时,经过寒暄后,一般面试官会让介绍项目经验。常见的问法是,说下你最近的(或最拿得出手的)一个项目。 根据我们的面试经验,发现有不少候选人对此没准备,说起来磕磕巴巴,甚…