Logo

Vue3组件销毁时如何正确清理input焦点相关资源

author
YGHub·2025-02-14·0·字数:322 字·阅读时间:2 分钟

让我们来看看如何在组件销毁时进行合理的清理工作。主要有以下几种情况需要注意:

1. 使用 onUnmounted 清理事件监听器

vue
// AutoFocusInput.vue
<template>
<input
ref="inputRef"
type="text"
@focus="handleFocus"
@blur="handleBlur"
/>
</template>
 
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
 
const inputRef = ref(null)
const focusHandler = () => {
console.log('input focused')
}
const blurHandler = () => {
console.log('input blurred')
}
 
onMounted(() => {
const input = inputRef.value
input.addEventListener('focus', focusHandler)
input.addEventListener('blur', blurHandler)
})
 
// 清理事件监听器
onUnmounted(() => {
const input = inputRef.value
if (input) {
input.removeEventListener('focus', focusHandler)
input.removeEventListener('blur', blurHandler)
}
})
</script>
 

2. 清理定时器

vue
// DelayFocusInput.vue
<template>
<input ref="inputRef" type="text" />
</template>
 
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
 
const inputRef = ref(null)
let focusTimer = null
 
onMounted(() => {
// 设置定时器
focusTimer = setTimeout(() => {
inputRef.value?.focus()
}, 1000)
})
 
// 清理定时器
onUnmounted(() => {
if (focusTimer) {
clearTimeout(focusTimer)
focusTimer = null
}
})
</script>
 

3. 自定义指令的清理

ts
// focus.ts
export const focus = {
mounted: (el, binding) => {
// 保存原始的tabIndex
el._originalTabIndex = el.tabIndex
el.focus()
// 添加事件监听器
el._focusHandler = () => {
console.log('focused')
}
el.addEventListener('focus', el._focusHandler)
},
// 在指令卸载时进行清理
unmounted: (el) => {
// 恢复原始tabIndex
if (el._originalTabIndex !== undefined) {
el.tabIndex = el._originalTabIndex
}
// 移除事件监听器
if (el._focusHandler) {
el.removeEventListener('focus', el._focusHandler)
delete el._focusHandler
}
}
}
 

4. 处理异步操作的清理

vue
// AsyncFocusInput.vue
<template>
<input ref="inputRef" type="text" />
</template>
 
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
 
const inputRef = ref(null)
let isComponentMounted = true
 
onMounted(async () => {
try {
// 模拟异步操作
await new Promise(resolve => setTimeout(resolve, 1000))
// 确保组件仍然挂载着再执行操作
if (isComponentMounted && inputRef.value) {
inputRef.value.focus()
}
} catch (error) {
console.error('聚焦失败:', error)
}
})
 
// 标记组件已卸载
onUnmounted(() => {
isComponentMounted = false
})
</script>
 

5.需要注意的要点:

1.为什么要清理?

  • 避免内存泄漏

  • 防止已卸载组件上的操作

  • 确保资源得到正确释放

2.清理的时机:

  • 组件卸载时(onUnmounted)

  • 指令卸载时(unmounted钩子)

  • 监听器停止时(watch的onStop回调)

3.常见的清理对象:

  • 事件监听器

  • 定时器

  • DOM引用

  • 自定义事件

  • 异步操作的标记

4.最佳实践:

  • 养成配对的习惯:有创建就要有销毁

  • 使用标志位控制异步操作

  • 及时解除DOM引用

  • 清理时进行空值检查

总结

通过以上的清理工作,可以有效避免内存泄漏,保持应用的性能和稳定性。在实际开发中,根据具体场景选择合适的清理策略非常重要。

Preview

点个赞 ~

版权申明: © 本文著作权归YGHub所有,未经YGHub网授权许可,禁止第三方以任何形式转载和使用本文内容。