wip(vapor): simplified builtin directive v-show
This commit is contained in:
parent
9f1025d854
commit
e5af194486
|
@ -12,20 +12,20 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > custom directive > basic 1`] = `
|
exports[`compile > custom directive > basic 1`] = `
|
||||||
"import { resolveDirective as _resolveDirective, withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { resolveDirective as _resolveDirective, withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const _directive_test = _resolveDirective("test")
|
const _directive_test = _resolveDirective("test")
|
||||||
const _directive_hello = _resolveDirective("hello")
|
const _directive_hello = _resolveDirective("hello")
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_directive_test], [_directive_hello, void 0, void 0, { world: true }]])
|
_withVaporDirectives(n0, [[_directive_test], [_directive_hello, void 0, void 0, { world: true }]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > custom directive > component 1`] = `
|
exports[`compile > custom directive > component 1`] = `
|
||||||
"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponentWithFallback as _createComponentWithFallback, withDirectives as _withDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue';
|
"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>")
|
const t0 = _template("<div></div>")
|
||||||
|
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
|
@ -38,91 +38,91 @@ export function render(_ctx) {
|
||||||
const n0 = _createIf(() => (true), () => {
|
const n0 = _createIf(() => (true), () => {
|
||||||
const n3 = t0()
|
const n3 = t0()
|
||||||
const n2 = _createComponentWithFallback(_component_Bar)
|
const n2 = _createComponentWithFallback(_component_Bar)
|
||||||
_withDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
|
_withVaporDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
|
||||||
_insert(n2, n3)
|
_insert(n2, n3)
|
||||||
return n3
|
return n3
|
||||||
})
|
})
|
||||||
return n0
|
return n0
|
||||||
}
|
}
|
||||||
}, true)
|
}, true)
|
||||||
_withDirectives(n4, [[_directive_test]])
|
_withVaporDirectives(n4, [[_directive_test]])
|
||||||
return n4
|
return n4
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > basic 1`] = `
|
exports[`compile > directives > custom directive > basic 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample]])
|
_withVaporDirectives(n0, [[_ctx.vExample]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > binding value 1`] = `
|
exports[`compile > directives > custom directive > binding value 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg]])
|
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > dynamic parameters 1`] = `
|
exports[`compile > directives > custom directive > dynamic parameters 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, _ctx.foo]])
|
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, _ctx.foo]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > modifiers 1`] = `
|
exports[`compile > directives > custom directive > modifiers 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, void 0, { bar: true }]])
|
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, void 0, { bar: true }]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > modifiers w/o binding 1`] = `
|
exports[`compile > directives > custom directive > modifiers w/o binding 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, void 0, void 0, { "foo-bar": true }]])
|
_withVaporDirectives(n0, [[_ctx.vExample, void 0, void 0, { "foo-bar": true }]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > static parameters 1`] = `
|
exports[`compile > directives > custom directive > static parameters 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo"]])
|
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo"]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compile > directives > custom directive > static parameters and modifiers 1`] = `
|
exports[`compile > directives > custom directive > static parameters and modifiers 1`] = `
|
||||||
"import { withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { withVaporDirectives as _withVaporDirectives, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo", { bar: true }]])
|
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo", { bar: true }]])
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`compiler: v-show transform > simple expression 1`] = `
|
exports[`compiler: v-show transform > simple expression 1`] = `
|
||||||
"import { vShow as _vShow, withDirectives as _withDirectives, template as _template } from 'vue';
|
"import { applyVShow as _applyVShow, template as _template } from 'vue';
|
||||||
const t0 = _template("<div></div>", true)
|
const t0 = _template("<div></div>", true)
|
||||||
|
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
_withDirectives(n0, [[_vShow, () => _ctx.foo]])
|
_applyVShow(n0, () => (_ctx.foo))
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -14,7 +14,7 @@ const compileWithVModel = makeCompile({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('compiler: vModel transform', () => {
|
describe.todo('compiler: vModel transform', () => {
|
||||||
test('should support simple expression', () => {
|
test('should support simple expression', () => {
|
||||||
const { code, helpers } = compileWithVModel('<input v-model="model" />')
|
const { code, helpers } = compileWithVModel('<input v-model="model" />')
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
|
|
@ -14,39 +14,64 @@ import {
|
||||||
genCall,
|
genCall,
|
||||||
genMulti,
|
genMulti,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import {
|
import { type DirectiveIRNode, IRNodeTypes, type OperationNode } from '../ir'
|
||||||
IRNodeTypes,
|
import { genVShow } from './vShow'
|
||||||
type OperationNode,
|
import { genVModel } from './vModel'
|
||||||
type WithDirectiveIRNode,
|
|
||||||
} from '../ir'
|
|
||||||
|
|
||||||
|
export function genBuiltinDirective(
|
||||||
|
oper: DirectiveIRNode,
|
||||||
|
context: CodegenContext,
|
||||||
|
): CodeFragment[] {
|
||||||
|
switch (oper.name) {
|
||||||
|
case 'show':
|
||||||
|
return genVShow(oper, context)
|
||||||
|
case 'model':
|
||||||
|
return genVModel(oper, context)
|
||||||
|
default:
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user directives via `withVaporDirectives`
|
||||||
|
* TODO the compiler side is implemented but no runtime support yet
|
||||||
|
* it was removed due to perf issues
|
||||||
|
*/
|
||||||
export function genDirectivesForElement(
|
export function genDirectivesForElement(
|
||||||
id: number,
|
id: number,
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
const dirs = filterDirectives(id, context.block.operation)
|
const dirs = filterCustomDirectives(id, context.block.operation)
|
||||||
return dirs.length ? genWithDirective(dirs, context) : []
|
return dirs.length ? genCustomDirectives(dirs, context) : []
|
||||||
}
|
}
|
||||||
|
|
||||||
export function genWithDirective(
|
function genCustomDirectives(
|
||||||
opers: WithDirectiveIRNode[],
|
opers: DirectiveIRNode[],
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
const { helper } = context
|
const { helper } = context
|
||||||
|
|
||||||
const element = `n${opers[0].element}`
|
const element = `n${opers[0].element}`
|
||||||
const directiveItems = opers.map(genDirective)
|
const directiveItems = opers.map(genDirectiveItem)
|
||||||
const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems)
|
const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems)
|
||||||
|
|
||||||
return [NEWLINE, ...genCall(helper('withDirectives'), element, directives)]
|
return [
|
||||||
|
NEWLINE,
|
||||||
|
// @ts-expect-error
|
||||||
|
...genCall(helper('withVaporDirectives'), element, directives),
|
||||||
|
]
|
||||||
|
|
||||||
function genDirective({
|
function genDirectiveItem({
|
||||||
dir,
|
dir,
|
||||||
name,
|
name,
|
||||||
builtin,
|
|
||||||
asset,
|
asset,
|
||||||
}: WithDirectiveIRNode): CodeFragment[] {
|
}: DirectiveIRNode): CodeFragment[] {
|
||||||
const directive = genDirective()
|
const directiveVar = asset
|
||||||
|
? toValidAssetId(name, 'directive')
|
||||||
|
: genExpression(
|
||||||
|
extend(createSimpleExpression(name, false), { ast: null }),
|
||||||
|
context,
|
||||||
|
)
|
||||||
const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
|
const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
|
||||||
const argument = dir.arg && genExpression(dir.arg, context)
|
const argument = dir.arg && genExpression(dir.arg, context)
|
||||||
const modifiers = !!dir.modifiers.length && [
|
const modifiers = !!dir.modifiers.length && [
|
||||||
|
@ -57,24 +82,11 @@ export function genWithDirective(
|
||||||
|
|
||||||
return genMulti(
|
return genMulti(
|
||||||
DELIMITERS_ARRAY.concat('void 0') as CodeFragmentDelimiters,
|
DELIMITERS_ARRAY.concat('void 0') as CodeFragmentDelimiters,
|
||||||
directive,
|
directiveVar,
|
||||||
value,
|
value,
|
||||||
argument,
|
argument,
|
||||||
modifiers,
|
modifiers,
|
||||||
)
|
)
|
||||||
|
|
||||||
function genDirective() {
|
|
||||||
if (builtin) {
|
|
||||||
return helper(name as any)
|
|
||||||
} else if (asset) {
|
|
||||||
return toValidAssetId(name, 'directive')
|
|
||||||
} else {
|
|
||||||
return genExpression(
|
|
||||||
extend(createSimpleExpression(name, false), { ast: null }),
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,12 +99,14 @@ export function genDirectiveModifiers(modifiers: string[]): string {
|
||||||
.join(', ')
|
.join(', ')
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterDirectives(
|
function filterCustomDirectives(
|
||||||
id: number,
|
id: number,
|
||||||
operations: OperationNode[],
|
operations: OperationNode[],
|
||||||
): WithDirectiveIRNode[] {
|
): DirectiveIRNode[] {
|
||||||
return operations.filter(
|
return operations.filter(
|
||||||
(oper): oper is WithDirectiveIRNode =>
|
(oper): oper is DirectiveIRNode =>
|
||||||
oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
|
oper.type === IRNodeTypes.DIRECTIVE &&
|
||||||
|
oper.element === id &&
|
||||||
|
!oper.builtin,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { genCreateComponent } from './component'
|
import { genCreateComponent } from './component'
|
||||||
import { genSlotOutlet } from './slotOutlet'
|
import { genSlotOutlet } from './slotOutlet'
|
||||||
import { processExpressions } from './expression'
|
import { processExpressions } from './expression'
|
||||||
|
import { genBuiltinDirective } from './directive'
|
||||||
|
|
||||||
export function genOperations(
|
export function genOperations(
|
||||||
opers: OperationNode[],
|
opers: OperationNode[],
|
||||||
|
@ -68,8 +69,8 @@ export function genOperation(
|
||||||
return genDeclareOldRef(oper)
|
return genDeclareOldRef(oper)
|
||||||
case IRNodeTypes.SLOT_OUTLET_NODE:
|
case IRNodeTypes.SLOT_OUTLET_NODE:
|
||||||
return genSlotOutlet(oper, context)
|
return genSlotOutlet(oper, context)
|
||||||
case IRNodeTypes.WITH_DIRECTIVE:
|
case IRNodeTypes.DIRECTIVE:
|
||||||
return [] // TODO
|
return genBuiltinDirective(oper, context)
|
||||||
default:
|
default:
|
||||||
const exhaustiveCheck: never = oper
|
const exhaustiveCheck: never = oper
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import type { CodegenContext } from '../generate'
|
||||||
|
import type { DirectiveIRNode } from '../ir'
|
||||||
|
import type { CodeFragment } from './utils'
|
||||||
|
|
||||||
|
export function genVModel(
|
||||||
|
oper: DirectiveIRNode,
|
||||||
|
context: CodegenContext,
|
||||||
|
): CodeFragment[] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
import { camelize } from '@vue/shared'
|
||||||
|
import { genExpression } from './expression'
|
||||||
|
import type { SetModelValueIRNode } from '../ir'
|
||||||
|
import { NEWLINE, genCall } from './utils'
|
||||||
|
import type { SimpleExpressionNode } from '@vue/compiler-dom'
|
||||||
|
|
||||||
|
export function genSetModelValue(
|
||||||
|
oper: SetModelValueIRNode,
|
||||||
|
context: CodegenContext,
|
||||||
|
): CodeFragment[] {
|
||||||
|
const { helper } = context
|
||||||
|
const name = oper.key.isStatic
|
||||||
|
? [JSON.stringify(`update:${camelize(oper.key.content)}`)]
|
||||||
|
: ['`update:${', ...genExpression(oper.key, context), '}`']
|
||||||
|
|
||||||
|
const handler = genModelHandler(oper.value, context)
|
||||||
|
|
||||||
|
return [
|
||||||
|
NEWLINE,
|
||||||
|
...genCall(helper('delegate'), `n${oper.element}`, name, handler),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function genModelHandler(
|
||||||
|
value: SimpleExpressionNode,
|
||||||
|
context: CodegenContext,
|
||||||
|
): CodeFragment[] {
|
||||||
|
const {
|
||||||
|
options: { isTS },
|
||||||
|
} = context
|
||||||
|
|
||||||
|
return [
|
||||||
|
`() => ${isTS ? `($event: any)` : `$event`} => (`,
|
||||||
|
...genExpression(value, context, '$event'),
|
||||||
|
')',
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import type { CodegenContext } from '../generate'
|
||||||
|
import type { DirectiveIRNode } from '../ir'
|
||||||
|
import { genExpression } from './expression'
|
||||||
|
import { type CodeFragment, NEWLINE, genCall } from './utils'
|
||||||
|
|
||||||
|
export function genVShow(
|
||||||
|
oper: DirectiveIRNode,
|
||||||
|
context: CodegenContext,
|
||||||
|
): CodeFragment[] {
|
||||||
|
return [
|
||||||
|
NEWLINE,
|
||||||
|
...genCall(context.helper('applyVShow'), `n${oper.element}`, [
|
||||||
|
`() => (`,
|
||||||
|
...genExpression(oper.dir.exp!, context),
|
||||||
|
`)`,
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ export enum IRNodeTypes {
|
||||||
CREATE_COMPONENT_NODE,
|
CREATE_COMPONENT_NODE,
|
||||||
SLOT_OUTLET_NODE,
|
SLOT_OUTLET_NODE,
|
||||||
|
|
||||||
WITH_DIRECTIVE,
|
DIRECTIVE,
|
||||||
DECLARE_OLD_REF, // consider make it more general
|
DECLARE_OLD_REF, // consider make it more general
|
||||||
|
|
||||||
IF,
|
IF,
|
||||||
|
@ -183,13 +183,14 @@ export interface PrependNodeIRNode extends BaseIRNode {
|
||||||
parent: number
|
parent: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WithDirectiveIRNode extends BaseIRNode {
|
export interface DirectiveIRNode extends BaseIRNode {
|
||||||
type: IRNodeTypes.WITH_DIRECTIVE
|
type: IRNodeTypes.DIRECTIVE
|
||||||
element: number
|
element: number
|
||||||
dir: VaporDirectiveNode
|
dir: VaporDirectiveNode
|
||||||
name: string
|
name: string
|
||||||
builtin?: boolean
|
builtin?: boolean
|
||||||
asset?: boolean
|
asset?: boolean
|
||||||
|
modelType?: 'text' | 'dynamic' | 'radio' | 'checkbox' | 'select'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateComponentIRNode extends BaseIRNode {
|
export interface CreateComponentIRNode extends BaseIRNode {
|
||||||
|
@ -230,7 +231,7 @@ export type OperationNode =
|
||||||
| CreateTextNodeIRNode
|
| CreateTextNodeIRNode
|
||||||
| InsertNodeIRNode
|
| InsertNodeIRNode
|
||||||
| PrependNodeIRNode
|
| PrependNodeIRNode
|
||||||
| WithDirectiveIRNode
|
| DirectiveIRNode
|
||||||
| IfIRNode
|
| IfIRNode
|
||||||
| ForIRNode
|
| ForIRNode
|
||||||
| CreateComponentIRNode
|
| CreateComponentIRNode
|
||||||
|
|
|
@ -381,7 +381,7 @@ function transformProp(
|
||||||
}
|
}
|
||||||
|
|
||||||
context.registerOperation({
|
context.registerOperation({
|
||||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
type: IRNodeTypes.DIRECTIVE,
|
||||||
element: context.reference(),
|
element: context.reference(),
|
||||||
dir: prop,
|
dir: prop,
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -13,11 +13,11 @@ import {
|
||||||
import type { NodeTransform, TransformContext } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import {
|
import {
|
||||||
type BlockIRNode,
|
type BlockIRNode,
|
||||||
|
type DirectiveIRNode,
|
||||||
DynamicFlag,
|
DynamicFlag,
|
||||||
IRNodeTypes,
|
IRNodeTypes,
|
||||||
type IRProps,
|
type IRProps,
|
||||||
type VaporDirectiveNode,
|
type VaporDirectiveNode,
|
||||||
type WithDirectiveIRNode,
|
|
||||||
} from '../ir'
|
} from '../ir'
|
||||||
import { camelize, extend } from '@vue/shared'
|
import { camelize, extend } from '@vue/shared'
|
||||||
import { newBlock } from './utils'
|
import { newBlock } from './utils'
|
||||||
|
@ -85,8 +85,8 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||||
irProps = isDynamic ? props : [props]
|
irProps = isDynamic ? props : [props]
|
||||||
|
|
||||||
const runtimeDirective = context.block.operation.find(
|
const runtimeDirective = context.block.operation.find(
|
||||||
(oper): oper is WithDirectiveIRNode =>
|
(oper): oper is DirectiveIRNode =>
|
||||||
oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
|
oper.type === IRNodeTypes.DIRECTIVE && oper.element === id,
|
||||||
)
|
)
|
||||||
if (runtimeDirective) {
|
if (runtimeDirective) {
|
||||||
context.options.onError(
|
context.options.onError(
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
isStaticArgOf,
|
isStaticArgOf,
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import type { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform } from '../transform'
|
||||||
import { IRNodeTypes } from '../ir'
|
import { type DirectiveIRNode, IRNodeTypes } from '../ir'
|
||||||
|
|
||||||
export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
const { exp, arg } = dir
|
const { exp, arg } = dir
|
||||||
|
@ -79,7 +79,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
)
|
)
|
||||||
const { tag } = node
|
const { tag } = node
|
||||||
const isCustomElement = context.options.isCustomElement(tag)
|
const isCustomElement = context.options.isCustomElement(tag)
|
||||||
let runtimeDirective: string | undefined = 'vModelText'
|
let modelType: DirectiveIRNode['modelType'] | undefined = 'text'
|
||||||
// TODO let runtimeDirective: VaporHelper | undefined = 'vModelText'
|
// TODO let runtimeDirective: VaporHelper | undefined = 'vModelText'
|
||||||
if (
|
if (
|
||||||
tag === 'input' ||
|
tag === 'input' ||
|
||||||
|
@ -92,17 +92,17 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
if (type) {
|
if (type) {
|
||||||
if (type.type === NodeTypes.DIRECTIVE) {
|
if (type.type === NodeTypes.DIRECTIVE) {
|
||||||
// :type="foo"
|
// :type="foo"
|
||||||
runtimeDirective = 'vModelDynamic'
|
modelType = 'dynamic'
|
||||||
} else if (type.value) {
|
} else if (type.value) {
|
||||||
switch (type.value.content) {
|
switch (type.value.content) {
|
||||||
case 'radio':
|
case 'radio':
|
||||||
runtimeDirective = 'vModelRadio'
|
modelType = 'radio'
|
||||||
break
|
break
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
runtimeDirective = 'vModelCheckbox'
|
modelType = 'checkbox'
|
||||||
break
|
break
|
||||||
case 'file':
|
case 'file':
|
||||||
runtimeDirective = undefined
|
modelType = undefined
|
||||||
context.options.onError(
|
context.options.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||||
|
@ -119,13 +119,13 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
} else if (hasDynamicKeyVBind(node)) {
|
} else if (hasDynamicKeyVBind(node)) {
|
||||||
// element has bindings with dynamic keys, which can possibly contain
|
// element has bindings with dynamic keys, which can possibly contain
|
||||||
// "type".
|
// "type".
|
||||||
runtimeDirective = 'vModelDynamic'
|
modelType = 'dynamic'
|
||||||
} else {
|
} else {
|
||||||
// text type
|
// text type
|
||||||
__DEV__ && checkDuplicatedValue()
|
__DEV__ && checkDuplicatedValue()
|
||||||
}
|
}
|
||||||
} else if (tag === 'select') {
|
} else if (tag === 'select') {
|
||||||
runtimeDirective = 'vModelSelect'
|
modelType = 'select'
|
||||||
} else {
|
} else {
|
||||||
// textarea
|
// textarea
|
||||||
__DEV__ && checkDuplicatedValue()
|
__DEV__ && checkDuplicatedValue()
|
||||||
|
@ -139,6 +139,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this should no longer be needed
|
||||||
context.registerOperation({
|
context.registerOperation({
|
||||||
type: IRNodeTypes.SET_MODEL_VALUE,
|
type: IRNodeTypes.SET_MODEL_VALUE,
|
||||||
element: context.reference(),
|
element: context.reference(),
|
||||||
|
@ -147,12 +148,13 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||||
isComponent,
|
isComponent,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (runtimeDirective)
|
if (modelType)
|
||||||
context.registerOperation({
|
context.registerOperation({
|
||||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
type: IRNodeTypes.DIRECTIVE,
|
||||||
element: context.reference(),
|
element: context.reference(),
|
||||||
dir,
|
dir,
|
||||||
name: runtimeDirective,
|
name: 'model',
|
||||||
|
modelType,
|
||||||
builtin: true,
|
builtin: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
|
import {
|
||||||
|
DOMErrorCodes,
|
||||||
|
ElementTypes,
|
||||||
|
ErrorCodes,
|
||||||
|
createCompilerError,
|
||||||
|
createDOMCompilerError,
|
||||||
|
} from '@vue/compiler-dom'
|
||||||
import type { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform } from '../transform'
|
||||||
import { IRNodeTypes } from '../ir'
|
import { IRNodeTypes } from '../ir'
|
||||||
|
|
||||||
|
@ -8,13 +14,24 @@ export const transformVShow: DirectiveTransform = (dir, node, context) => {
|
||||||
context.options.onError(
|
context.options.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),
|
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),
|
||||||
)
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.tagType === ElementTypes.SLOT) {
|
||||||
|
context.options.onError(
|
||||||
|
createCompilerError(
|
||||||
|
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
||||||
|
loc,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
context.registerOperation({
|
context.registerOperation({
|
||||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
type: IRNodeTypes.DIRECTIVE,
|
||||||
element: context.reference(),
|
element: context.reference(),
|
||||||
dir,
|
dir,
|
||||||
name: 'vShow',
|
name: 'show',
|
||||||
builtin: true,
|
builtin: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
import type { ObjectDirective } from '@vue/runtime-core'
|
import type { ObjectDirective } from '@vue/runtime-core'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export const vShowOriginalDisplay: unique symbol = Symbol('_vod')
|
export const vShowOriginalDisplay: unique symbol = Symbol('_vod')
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export const vShowHidden: unique symbol = Symbol('_vsh')
|
export const vShowHidden: unique symbol = Symbol('_vsh')
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
export interface VShowElement extends HTMLElement {
|
export interface VShowElement extends HTMLElement {
|
||||||
// _vod = vue original display
|
// _vod = vue original display
|
||||||
[vShowOriginalDisplay]: string
|
[vShowOriginalDisplay]: string
|
||||||
|
|
|
@ -322,3 +322,11 @@ export { patchStyle } from './modules/style'
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export { shouldSetAsProp } from './patchProp'
|
export { shouldSetAsProp } from './patchProp'
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export {
|
||||||
|
vShowOriginalDisplay,
|
||||||
|
vShowHidden,
|
||||||
|
type VShowElement,
|
||||||
|
} from './directives/vShow'
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import {
|
||||||
|
type VShowElement,
|
||||||
|
vShowHidden,
|
||||||
|
vShowOriginalDisplay,
|
||||||
|
} from '@vue/runtime-dom'
|
||||||
|
import { renderEffect } from '../renderEffect'
|
||||||
|
|
||||||
|
export function applyVShow(el: VShowElement, source: () => any): void {
|
||||||
|
el[vShowOriginalDisplay] = el.style.display === 'none' ? '' : el.style.display
|
||||||
|
renderEffect(() => setDisplay(el, source()))
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDisplay(el: VShowElement, value: unknown): void {
|
||||||
|
el.style.display = value ? el[vShowOriginalDisplay] : 'none'
|
||||||
|
el[vShowHidden] = !value
|
||||||
|
}
|
|
@ -30,3 +30,4 @@ export {
|
||||||
} from './apiCreateFor'
|
} from './apiCreateFor'
|
||||||
export { createTemplateRefSetter } from './apiTemplateRef'
|
export { createTemplateRefSetter } from './apiTemplateRef'
|
||||||
export { createDynamicComponent } from './apiCreateDynamicComponent'
|
export { createDynamicComponent } from './apiCreateDynamicComponent'
|
||||||
|
export { applyVShow } from './directives/vShow'
|
||||||
|
|
Loading…
Reference in New Issue