From: Evan You Date: Sat, 8 Feb 2025 13:32:16 +0000 (+0800) Subject: wip(vapor): custom directives X-Git-Tag: v3.6.0-alpha.1~16^2~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8549a243a5fa6008963a9d80a32ed86422227a0c;p=thirdparty%2Fvuejs%2Fcore.git wip(vapor): custom directives --- diff --git a/packages/compiler-vapor/src/generators/directive.ts b/packages/compiler-vapor/src/generators/directive.ts index 6321ad216f..7ed4624c1f 100644 --- a/packages/compiler-vapor/src/generators/directive.ts +++ b/packages/compiler-vapor/src/generators/directive.ts @@ -57,7 +57,6 @@ function genCustomDirectives( return [ NEWLINE, - // @ts-expect-error ...genCall(helper('withVaporDirectives'), element, directives), ] diff --git a/packages/runtime-vapor/src/directives/custom.ts b/packages/runtime-vapor/src/directives/custom.ts new file mode 100644 index 0000000000..06a5a99cd9 --- /dev/null +++ b/packages/runtime-vapor/src/directives/custom.ts @@ -0,0 +1,36 @@ +import type { DirectiveModifiers } from '@vue/runtime-dom' +import type { VaporComponentInstance } from '../component' +import { renderEffect } from '../renderEffect' + +// !! vapor directive is different from vdom directives +export type VaporDirective = ( + node: Element | VaporComponentInstance, + value?: () => any, + argument?: string, + modifiers?: DirectiveModifiers, +) => (() => void) | void + +type DirectiveArguments = Array< + | [VaporDirective | undefined] + | [VaporDirective | undefined, () => any] + | [VaporDirective | undefined, () => any, argument: string] + | [ + VaporDirective | undefined, + value: () => any, + argument: string, + modifiers: DirectiveModifiers, + ] +> + +export function withVaporDirectives( + node: Element | VaporComponentInstance, + dirs: DirectiveArguments, +): void { + // TODO handle custom directive on component + for (const [dir, value, argument, modifiers] of dirs) { + if (dir) { + const ret = dir(node, value, argument, modifiers) + if (ret) renderEffect(ret) + } + } +} diff --git a/packages/runtime-vapor/src/directives/vModel.ts b/packages/runtime-vapor/src/directives/vModel.ts index 12dfb81ff1..0c32b24bf4 100644 --- a/packages/runtime-vapor/src/directives/vModel.ts +++ b/packages/runtime-vapor/src/directives/vModel.ts @@ -1,4 +1,5 @@ import { + currentInstance, onMounted, vModelCheckboxInit, vModelCheckboxUpdate, @@ -26,12 +27,20 @@ type VaporModelDirective< modifiers?: { [key in Modifiers]?: true }, ) => void +function ensureMounted(cb: () => void) { + if (currentInstance!.isMounted) { + cb() + } else { + onMounted(cb) + } +} + export const applyTextModel: VaporModelDirective< HTMLInputElement | HTMLTextAreaElement, 'trim' | 'number' | 'lazy' > = (el, get, set, { trim, number, lazy } = {}) => { vModelTextInit(el, trim, number, lazy, set) - onMounted(() => { + ensureMounted(() => { let value: any renderEffect(() => { vModelTextUpdate(el, value, (value = get()), trim, number, lazy) @@ -45,7 +54,7 @@ export const applyCheckboxModel: VaporModelDirective = ( set, ) => { vModelCheckboxInit(el, set) - onMounted(() => { + ensureMounted(() => { let value: any renderEffect(() => { vModelCheckboxUpdate( @@ -64,7 +73,7 @@ export const applyRadioModel: VaporModelDirective = ( set, ) => { addEventListener(el, 'change', () => set(vModelGetValue(el))) - onMounted(() => { + ensureMounted(() => { let value: any renderEffect(() => { if (value !== (value = get())) { @@ -79,7 +88,7 @@ export const applySelectModel: VaporModelDirective< 'number' > = (el, get, set, modifiers) => { vModelSelectInit(el, get(), modifiers && modifiers.number, set) - onMounted(() => { + ensureMounted(() => { renderEffect(() => vModelSetSelected(el, traverse(get()))) }) } diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts index 808a5f46e4..85f1bc5eac 100644 --- a/packages/runtime-vapor/src/index.ts +++ b/packages/runtime-vapor/src/index.ts @@ -2,6 +2,7 @@ export { createVaporApp } from './apiCreateApp' export { defineVaporComponent } from './apiDefineComponent' export { vaporInteropPlugin } from './vdomInterop' +export type { VaporDirective } from './directives/custom' // compiler-use only export { insert, prepend, remove } from './block' @@ -39,3 +40,4 @@ export { applySelectModel, applyDynamicModel, } from './directives/vModel' +export { withVaporDirectives } from './directives/custom'