wip(vapor): custom directives

This commit is contained in:
Evan You 2025-02-08 21:32:16 +08:00
parent cd93dad4d9
commit 8549a243a5
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
4 changed files with 51 additions and 5 deletions

View File

@ -57,7 +57,6 @@ function genCustomDirectives(
return [ return [
NEWLINE, NEWLINE,
// @ts-expect-error
...genCall(helper('withVaporDirectives'), element, directives), ...genCall(helper('withVaporDirectives'), element, directives),
] ]

View File

@ -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)
}
}
}

View File

@ -1,4 +1,5 @@
import { import {
currentInstance,
onMounted, onMounted,
vModelCheckboxInit, vModelCheckboxInit,
vModelCheckboxUpdate, vModelCheckboxUpdate,
@ -26,12 +27,20 @@ type VaporModelDirective<
modifiers?: { [key in Modifiers]?: true }, modifiers?: { [key in Modifiers]?: true },
) => void ) => void
function ensureMounted(cb: () => void) {
if (currentInstance!.isMounted) {
cb()
} else {
onMounted(cb)
}
}
export const applyTextModel: VaporModelDirective< export const applyTextModel: VaporModelDirective<
HTMLInputElement | HTMLTextAreaElement, HTMLInputElement | HTMLTextAreaElement,
'trim' | 'number' | 'lazy' 'trim' | 'number' | 'lazy'
> = (el, get, set, { trim, number, lazy } = {}) => { > = (el, get, set, { trim, number, lazy } = {}) => {
vModelTextInit(el, trim, number, lazy, set) vModelTextInit(el, trim, number, lazy, set)
onMounted(() => { ensureMounted(() => {
let value: any let value: any
renderEffect(() => { renderEffect(() => {
vModelTextUpdate(el, value, (value = get()), trim, number, lazy) vModelTextUpdate(el, value, (value = get()), trim, number, lazy)
@ -45,7 +54,7 @@ export const applyCheckboxModel: VaporModelDirective<HTMLInputElement> = (
set, set,
) => { ) => {
vModelCheckboxInit(el, set) vModelCheckboxInit(el, set)
onMounted(() => { ensureMounted(() => {
let value: any let value: any
renderEffect(() => { renderEffect(() => {
vModelCheckboxUpdate( vModelCheckboxUpdate(
@ -64,7 +73,7 @@ export const applyRadioModel: VaporModelDirective<HTMLInputElement> = (
set, set,
) => { ) => {
addEventListener(el, 'change', () => set(vModelGetValue(el))) addEventListener(el, 'change', () => set(vModelGetValue(el)))
onMounted(() => { ensureMounted(() => {
let value: any let value: any
renderEffect(() => { renderEffect(() => {
if (value !== (value = get())) { if (value !== (value = get())) {
@ -79,7 +88,7 @@ export const applySelectModel: VaporModelDirective<
'number' 'number'
> = (el, get, set, modifiers) => { > = (el, get, set, modifiers) => {
vModelSelectInit(el, get(), modifiers && modifiers.number, set) vModelSelectInit(el, get(), modifiers && modifiers.number, set)
onMounted(() => { ensureMounted(() => {
renderEffect(() => vModelSetSelected(el, traverse(get()))) renderEffect(() => vModelSetSelected(el, traverse(get())))
}) })
} }

View File

@ -2,6 +2,7 @@
export { createVaporApp } from './apiCreateApp' export { createVaporApp } from './apiCreateApp'
export { defineVaporComponent } from './apiDefineComponent' export { defineVaporComponent } from './apiDefineComponent'
export { vaporInteropPlugin } from './vdomInterop' export { vaporInteropPlugin } from './vdomInterop'
export type { VaporDirective } from './directives/custom'
// compiler-use only // compiler-use only
export { insert, prepend, remove } from './block' export { insert, prepend, remove } from './block'
@ -39,3 +40,4 @@ export {
applySelectModel, applySelectModel,
applyDynamicModel, applyDynamicModel,
} from './directives/vModel' } from './directives/vModel'
export { withVaporDirectives } from './directives/custom'