From f40757377c336bc287a320516f417597db1172c3 Mon Sep 17 00:00:00 2001 From: zhengchangfu Date: Wed, 4 Sep 2024 14:04:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(n-cascader):=20=E4=BF=AE=E5=A4=8D=E6=9C=AA?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E7=A7=BB=E9=99=A4=E4=BA=8B=E4=BB=B6=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.zh-CN.md | 1 + src/_utils/composable/use-resize.ts | 29 +++++++++++++++++++++++++++-- src/cascader/src/CascaderMenu.tsx | 3 ++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index cdbd1701136..336f53f4a1a 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -23,6 +23,7 @@ - 修复 `n-icon` 的 `component` 属性不接受 FunctionalComponent 问题 - 修复 `n-mention` 的面板在 `placement` 设为 `'top'` 或者组件设定的 padding 的时候位置有问题,关闭 [#6241](https://github.com/tusen-ai/naive-ui/issues/6241) - 修复 `n-carousel` 中轮播图的过渡行为不符合预期问题,关闭 [#5993](https://github.com/tusen-ai/naive-ui/issues/5993) +- 修复 `n-cascader` 内存泄漏问题,关闭 [#6200](https://github.com/tusen-ai/naive-ui/issues/6200) ### Features diff --git a/src/_utils/composable/use-resize.ts b/src/_utils/composable/use-resize.ts index 21d1b421dc6..fb0a2401d47 100644 --- a/src/_utils/composable/use-resize.ts +++ b/src/_utils/composable/use-resize.ts @@ -1,9 +1,25 @@ -import { type Ref, onBeforeUnmount, onMounted } from 'vue' +import { + type Ref, + isRef, + onBeforeUnmount, + onBeforeUpdate, + onMounted +} from 'vue' import { resizeObserverManager } from 'vueuc' +interface UseOnResizeOptions { + /** + * In some cases + * if a reactive variable is used in the render function to control whether or not the dom is rendered, + * the event cannot be cleared in onBeforeUnmount because the dom no longer exists, + * but the event contains a reference to the dom, resulting in a memory leak + */ + show?: Ref +} export function useOnResize( elRef: Ref, - onResize: (() => void) | undefined + onResize: (() => void) | undefined, + options?: UseOnResizeOptions ): void { // it needn't be reactive since it's for internal usage if (onResize) { @@ -19,5 +35,14 @@ export function useOnResize( resizeObserverManager.unregisterHandler(el) } }) + if (options?.show && isRef(options.show)) { + onBeforeUpdate(() => { + const { value: el } = elRef + const { value: show } = options.show! + if (!show && el) { + resizeObserverManager.unregisterHandler(el) + } + }) + } } } diff --git a/src/cascader/src/CascaderMenu.tsx b/src/cascader/src/CascaderMenu.tsx index b8fc91b3836..d37c19e0a00 100644 --- a/src/cascader/src/CascaderMenu.tsx +++ b/src/cascader/src/CascaderMenu.tsx @@ -5,6 +5,7 @@ import { h, inject, ref, + toRef, withDirectives } from 'vue' import type { FollowerPlacement } from 'vueuc' @@ -74,7 +75,7 @@ export default defineComponent({ function handleResize(): void { syncCascaderMenuPosition() } - useOnResize(selfElRef, handleResize) + useOnResize(selfElRef, handleResize, { show: toRef(props, 'show') }) function showErrorMessage(label: string): void { const { value: { loadingRequiredMessage }