From cc7df9aa1dd3846292c4b0dbc74f450b44fd6781 Mon Sep 17 00:00:00 2001 From: Doctorwu Date: Thu, 15 Feb 2024 20:07:40 +0800 Subject: [PATCH] feat: use postFlush instead of promise --- packages/runtime-core/src/directives.ts | 9 ++++++++ packages/runtime-dom/src/directives/vShow.ts | 22 ++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/runtime-core/src/directives.ts b/packages/runtime-core/src/directives.ts index daaf28b1518..4f060a199b7 100644 --- a/packages/runtime-core/src/directives.ts +++ b/packages/runtime-core/src/directives.ts @@ -40,6 +40,9 @@ export type DirectiveHook | null, V = any> = ( binding: DirectiveBinding, vnode: VNode, prevVNode: Prev, + // register a callback witch will be called + // after all dirHooks have been executed + postFlushDirs?: (fn: () => void) => void, ) => void export type SSRDirectiveHook = ( @@ -129,6 +132,7 @@ export function invokeDirectiveHook( ) { const bindings = vnode.dirs! const oldBindings = prevVNode && prevVNode.dirs! + const postFlushDirsQueue: (() => void)[] = [] for (let i = 0; i < bindings.length; i++) { const binding = bindings[i] if (oldBindings) { @@ -147,8 +151,13 @@ export function invokeDirectiveHook( binding, vnode, prevVNode, + (fn: () => void) => { + postFlushDirsQueue.push(fn) + }, ]) resetTracking() } } + postFlushDirsQueue.forEach(postDir => postDir()) + postFlushDirsQueue.length = 0 } diff --git a/packages/runtime-dom/src/directives/vShow.ts b/packages/runtime-dom/src/directives/vShow.ts index e9c21b1b4fe..7f43783f9b7 100644 --- a/packages/runtime-dom/src/directives/vShow.ts +++ b/packages/runtime-dom/src/directives/vShow.ts @@ -7,8 +7,6 @@ interface VShowElement extends HTMLElement { [vShowOriginalDisplay]: string } -const resolvedPromise = Promise.resolve() - export const vShow: ObjectDirective & { name?: 'show' } = { beforeMount(el, { value }, { transition }) { el[vShowOriginalDisplay] = @@ -24,7 +22,7 @@ export const vShow: ObjectDirective & { name?: 'show' } = { transition.enter(el) } }, - updated(el, { value, oldValue }, { transition }) { + updated(el, { value, oldValue }, { transition }, _, postFlush) { if ( !value === !oldValue && (el.style.display === el[vShowOriginalDisplay] || (!value && transition)) @@ -32,9 +30,11 @@ export const vShow: ObjectDirective & { name?: 'show' } = { return if (transition) { if (value) { - transition.beforeEnter(el) - setDisplay(el, true) - transition.enter(el) + postFlush!(() => { + transition.beforeEnter(el) + setDisplay(el, true) + transition.enter(el) + }) } else { transition.leave(el, () => { setDisplay(el, false) @@ -44,7 +44,9 @@ export const vShow: ObjectDirective & { name?: 'show' } = { // #10038 // when multi vShow be applied to the same element // and the sync setDisplay will impact other vShow - postSetDisplay(el, value) + postFlush!(() => { + setDisplay(el, value) + }) } }, beforeUnmount(el, { value }) { @@ -60,12 +62,6 @@ function setDisplay(el: VShowElement, value: unknown): void { el.style.display = value ? el[vShowOriginalDisplay] : 'none' } -function postSetDisplay(el: VShowElement, value: unknown): void { - resolvedPromise.then(() => { - setDisplay(el, value) - }) -} - // SSR vnode transforms, only used when user includes client-oriented render // function in SSR export function initVShowForSSR() {