diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index f91af6c7399..64ef565e20b 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -427,6 +427,17 @@ export interface GenericComponentInstance { * @internal */ suspense: SuspenseBoundary | null + /** + * `updateTeleportCssVars` + * For updating css vars on contained teleports + * @internal + */ + ut?: (vars?: Record) => void + /** + * dev only. For style v-bind hydration mismatch checks + * @internal + */ + getCssVars?: () => Record // lifecycle /** @@ -651,19 +662,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance { * @internal */ n?: () => Promise - /** - * `updateTeleportCssVars` - * For updating css vars on contained teleports - * @internal - */ - ut?: (vars?: Record) => void - - /** - * dev only. For style v-bind hydration mismatch checks - * @internal - */ - getCssVars?: () => Record - /** * v2 compat only, for caching mutated $options * @internal diff --git a/packages/runtime-dom/src/helpers/useCssVars.ts b/packages/runtime-dom/src/helpers/useCssVars.ts index b25be09d212..cbaea4e8122 100644 --- a/packages/runtime-dom/src/helpers/useCssVars.ts +++ b/packages/runtime-dom/src/helpers/useCssVars.ts @@ -1,5 +1,6 @@ import { Fragment, + type GenericComponentInstance, Static, type VNode, getCurrentInstance, @@ -20,36 +21,22 @@ export const CSS_VAR_TEXT: unique symbol = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '') export function useCssVars(getter: (ctx: any) => Record): void { if (!__BROWSER__ && !__TEST__) return - const instance = getCurrentInstance() - /* v8 ignore start */ - if (!instance) { - __DEV__ && - warn(`useCssVars is called without current active component instance.`) - return - } - /* v8 ignore stop */ - - const updateTeleports = (instance.ut = (vars = getter(instance.proxy)) => { - Array.from( - document.querySelectorAll(`[data-v-owner="${instance.uid}"]`), - ).forEach(node => setVarsOnNode(node, vars)) - }) - - if (__DEV__) { - instance.getCssVars = () => getter(instance.proxy) - } - - const setVars = () => { - const vars = getter(instance.proxy) + const instance = getCurrentInstance()! // to be check in baseUseCssVars + const getVars = () => getter(instance.proxy) + const setVars = (vars: Record) => { if (instance.ce) { setVarsOnNode(instance.ce as any, vars) } else { setVarsOnVNode(instance.subTree, vars) } - updateTeleports(vars) } - applyCssVars(() => instance.subTree.el!.parentNode!, setVars) + baseUseCssVars( + instance, + () => instance.subTree.el!.parentNode!, + getVars, + setVars, + ) } function setVarsOnVNode(vnode: VNode, vars: Record) { @@ -82,20 +69,46 @@ function setVarsOnVNode(vnode: VNode, vars: Record) { } } -export function applyCssVars( +export function baseUseCssVars( + instance: GenericComponentInstance | null, getParentNode: () => Node, - setVars: () => void, + getVars: () => Record, + setVars: (vars: Record) => void, ): void { + /* v8 ignore start */ + if (!instance) { + __DEV__ && + warn(`useCssVars is called without current active component instance.`) + return + } + /* v8 ignore stop */ + + if (__DEV__) { + instance.getCssVars = () => getVars() + } + + const updateTeleports = (instance.ut = (vars = getVars()) => { + Array.from( + document.querySelectorAll(`[data-v-owner="${instance.uid}"]`), + ).forEach(node => setVarsOnNode(node, vars)) + }) + + const applyCssCars = () => { + const vars = getVars() + setVars(vars) + updateTeleports(vars) + } + // handle cases where child component root is affected // and triggers reflow in onMounted onBeforeUpdate(() => { - queuePostFlushCb(setVars) + queuePostFlushCb(applyCssCars) }) onMounted(() => { // run setVars synchronously here, but run as post-effect on changes - watch(setVars, NOOP, { flush: 'post' }) - const ob = new MutationObserver(setVars) + watch(applyCssCars, NOOP, { flush: 'post' }) + const ob = new MutationObserver(applyCssCars) ob.observe(getParentNode(), { childList: true }) onUnmounted(() => ob.disconnect()) }) diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index 66c69d374a7..4287e54c3f8 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -325,4 +325,4 @@ export { shouldSetAsProp } from './patchProp' /** * @internal */ -export { applyCssVars, setVarsOnNode } from './helpers/useCssVars' +export { baseUseCssVars, setVarsOnNode } from './helpers/useCssVars' diff --git a/packages/runtime-vapor/src/helpers/useCssVars.ts b/packages/runtime-vapor/src/helpers/useCssVars.ts index 91f75f75352..0f5fa2b0407 100644 --- a/packages/runtime-vapor/src/helpers/useCssVars.ts +++ b/packages/runtime-vapor/src/helpers/useCssVars.ts @@ -1,8 +1,7 @@ import { - applyCssVars, + baseUseCssVars, currentInstance, setVarsOnNode, - warn, } from '@vue/runtime-dom' import { type VaporComponentInstance, isVaporComponent } from '../component' import { isArray } from '@vue/shared' @@ -12,17 +11,11 @@ export function vaporUseCssVars(getter: () => Record): void { if (!__BROWSER__ && !__TEST__) return const instance = currentInstance as VaporComponentInstance - /* v8 ignore start */ - if (!instance) { - __DEV__ && - warn(`useCssVars is called without current active component instance.`) - return - } - /* v8 ignore stop */ - - applyCssVars( + baseUseCssVars( + instance, () => resolveParentNode(instance.block), - () => setVarsOnBlock(instance.block, getter()), + () => getter(), + vars => setVarsOnBlock(instance.block, vars), ) }