mirror of https://github.com/vuejs/core.git
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`] = `
|
||||
"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)
|
||||
|
||||
export function render(_ctx) {
|
||||
const _directive_test = _resolveDirective("test")
|
||||
const _directive_hello = _resolveDirective("hello")
|
||||
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
|
||||
}"
|
||||
`;
|
||||
|
||||
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>")
|
||||
|
||||
export function render(_ctx) {
|
||||
|
@ -38,91 +38,91 @@ export function render(_ctx) {
|
|||
const n0 = _createIf(() => (true), () => {
|
||||
const n3 = t0()
|
||||
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)
|
||||
return n3
|
||||
})
|
||||
return n0
|
||||
}
|
||||
}, true)
|
||||
_withDirectives(n4, [[_directive_test]])
|
||||
_withVaporDirectives(n4, [[_directive_test]])
|
||||
return n4
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_ctx.vExample]])
|
||||
_withVaporDirectives(n0, [[_ctx.vExample]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg]])
|
||||
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, _ctx.foo]])
|
||||
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, _ctx.foo]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
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
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
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
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo"]])
|
||||
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo"]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo", { bar: true }]])
|
||||
_withVaporDirectives(n0, [[_ctx.vExample, () => _ctx.msg, "foo", { bar: true }]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
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)
|
||||
|
||||
export function render(_ctx) {
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_vShow, () => _ctx.foo]])
|
||||
_applyVShow(n0, () => (_ctx.foo))
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -14,7 +14,7 @@ const compileWithVModel = makeCompile({
|
|||
},
|
||||
})
|
||||
|
||||
describe('compiler: vModel transform', () => {
|
||||
describe.todo('compiler: vModel transform', () => {
|
||||
test('should support simple expression', () => {
|
||||
const { code, helpers } = compileWithVModel('<input v-model="model" />')
|
||||
expect(code).toMatchSnapshot()
|
||||
|
|
|
@ -14,39 +14,64 @@ import {
|
|||
genCall,
|
||||
genMulti,
|
||||
} from './utils'
|
||||
import {
|
||||
IRNodeTypes,
|
||||
type OperationNode,
|
||||
type WithDirectiveIRNode,
|
||||
} from '../ir'
|
||||
import { type DirectiveIRNode, IRNodeTypes, type OperationNode } from '../ir'
|
||||
import { genVShow } from './vShow'
|
||||
import { genVModel } from './vModel'
|
||||
|
||||
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(
|
||||
id: number,
|
||||
context: CodegenContext,
|
||||
): CodeFragment[] {
|
||||
const dirs = filterDirectives(id, context.block.operation)
|
||||
return dirs.length ? genWithDirective(dirs, context) : []
|
||||
const dirs = filterCustomDirectives(id, context.block.operation)
|
||||
return dirs.length ? genCustomDirectives(dirs, context) : []
|
||||
}
|
||||
|
||||
export function genWithDirective(
|
||||
opers: WithDirectiveIRNode[],
|
||||
function genCustomDirectives(
|
||||
opers: DirectiveIRNode[],
|
||||
context: CodegenContext,
|
||||
): CodeFragment[] {
|
||||
const { helper } = context
|
||||
|
||||
const element = `n${opers[0].element}`
|
||||
const directiveItems = opers.map(genDirective)
|
||||
const directiveItems = opers.map(genDirectiveItem)
|
||||
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,
|
||||
name,
|
||||
builtin,
|
||||
asset,
|
||||
}: WithDirectiveIRNode): CodeFragment[] {
|
||||
const directive = genDirective()
|
||||
}: DirectiveIRNode): CodeFragment[] {
|
||||
const directiveVar = asset
|
||||
? toValidAssetId(name, 'directive')
|
||||
: genExpression(
|
||||
extend(createSimpleExpression(name, false), { ast: null }),
|
||||
context,
|
||||
)
|
||||
const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
|
||||
const argument = dir.arg && genExpression(dir.arg, context)
|
||||
const modifiers = !!dir.modifiers.length && [
|
||||
|
@ -57,24 +82,11 @@ export function genWithDirective(
|
|||
|
||||
return genMulti(
|
||||
DELIMITERS_ARRAY.concat('void 0') as CodeFragmentDelimiters,
|
||||
directive,
|
||||
directiveVar,
|
||||
value,
|
||||
argument,
|
||||
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(', ')
|
||||
}
|
||||
|
||||
function filterDirectives(
|
||||
function filterCustomDirectives(
|
||||
id: number,
|
||||
operations: OperationNode[],
|
||||
): WithDirectiveIRNode[] {
|
||||
): DirectiveIRNode[] {
|
||||
return operations.filter(
|
||||
(oper): oper is WithDirectiveIRNode =>
|
||||
oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
|
||||
(oper): oper is DirectiveIRNode =>
|
||||
oper.type === IRNodeTypes.DIRECTIVE &&
|
||||
oper.element === id &&
|
||||
!oper.builtin,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
import { genCreateComponent } from './component'
|
||||
import { genSlotOutlet } from './slotOutlet'
|
||||
import { processExpressions } from './expression'
|
||||
import { genBuiltinDirective } from './directive'
|
||||
|
||||
export function genOperations(
|
||||
opers: OperationNode[],
|
||||
|
@ -68,8 +69,8 @@ export function genOperation(
|
|||
return genDeclareOldRef(oper)
|
||||
case IRNodeTypes.SLOT_OUTLET_NODE:
|
||||
return genSlotOutlet(oper, context)
|
||||
case IRNodeTypes.WITH_DIRECTIVE:
|
||||
return [] // TODO
|
||||
case IRNodeTypes.DIRECTIVE:
|
||||
return genBuiltinDirective(oper, context)
|
||||
default:
|
||||
const exhaustiveCheck: never = oper
|
||||
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,
|
||||
SLOT_OUTLET_NODE,
|
||||
|
||||
WITH_DIRECTIVE,
|
||||
DIRECTIVE,
|
||||
DECLARE_OLD_REF, // consider make it more general
|
||||
|
||||
IF,
|
||||
|
@ -183,13 +183,14 @@ export interface PrependNodeIRNode extends BaseIRNode {
|
|||
parent: number
|
||||
}
|
||||
|
||||
export interface WithDirectiveIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.WITH_DIRECTIVE
|
||||
export interface DirectiveIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.DIRECTIVE
|
||||
element: number
|
||||
dir: VaporDirectiveNode
|
||||
name: string
|
||||
builtin?: boolean
|
||||
asset?: boolean
|
||||
modelType?: 'text' | 'dynamic' | 'radio' | 'checkbox' | 'select'
|
||||
}
|
||||
|
||||
export interface CreateComponentIRNode extends BaseIRNode {
|
||||
|
@ -230,7 +231,7 @@ export type OperationNode =
|
|||
| CreateTextNodeIRNode
|
||||
| InsertNodeIRNode
|
||||
| PrependNodeIRNode
|
||||
| WithDirectiveIRNode
|
||||
| DirectiveIRNode
|
||||
| IfIRNode
|
||||
| ForIRNode
|
||||
| CreateComponentIRNode
|
||||
|
|
|
@ -381,7 +381,7 @@ function transformProp(
|
|||
}
|
||||
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
type: IRNodeTypes.DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir: prop,
|
||||
name,
|
||||
|
|
|
@ -13,11 +13,11 @@ import {
|
|||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
type BlockIRNode,
|
||||
type DirectiveIRNode,
|
||||
DynamicFlag,
|
||||
IRNodeTypes,
|
||||
type IRProps,
|
||||
type VaporDirectiveNode,
|
||||
type WithDirectiveIRNode,
|
||||
} from '../ir'
|
||||
import { camelize, extend } from '@vue/shared'
|
||||
import { newBlock } from './utils'
|
||||
|
@ -85,8 +85,8 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||
irProps = isDynamic ? props : [props]
|
||||
|
||||
const runtimeDirective = context.block.operation.find(
|
||||
(oper): oper is WithDirectiveIRNode =>
|
||||
oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
|
||||
(oper): oper is DirectiveIRNode =>
|
||||
oper.type === IRNodeTypes.DIRECTIVE && oper.element === id,
|
||||
)
|
||||
if (runtimeDirective) {
|
||||
context.options.onError(
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
isStaticArgOf,
|
||||
} from '@vue/compiler-dom'
|
||||
import type { DirectiveTransform } from '../transform'
|
||||
import { IRNodeTypes } from '../ir'
|
||||
import { type DirectiveIRNode, IRNodeTypes } from '../ir'
|
||||
|
||||
export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
||||
const { exp, arg } = dir
|
||||
|
@ -79,7 +79,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
)
|
||||
const { tag } = node
|
||||
const isCustomElement = context.options.isCustomElement(tag)
|
||||
let runtimeDirective: string | undefined = 'vModelText'
|
||||
let modelType: DirectiveIRNode['modelType'] | undefined = 'text'
|
||||
// TODO let runtimeDirective: VaporHelper | undefined = 'vModelText'
|
||||
if (
|
||||
tag === 'input' ||
|
||||
|
@ -92,17 +92,17 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
if (type) {
|
||||
if (type.type === NodeTypes.DIRECTIVE) {
|
||||
// :type="foo"
|
||||
runtimeDirective = 'vModelDynamic'
|
||||
modelType = 'dynamic'
|
||||
} else if (type.value) {
|
||||
switch (type.value.content) {
|
||||
case 'radio':
|
||||
runtimeDirective = 'vModelRadio'
|
||||
modelType = 'radio'
|
||||
break
|
||||
case 'checkbox':
|
||||
runtimeDirective = 'vModelCheckbox'
|
||||
modelType = 'checkbox'
|
||||
break
|
||||
case 'file':
|
||||
runtimeDirective = undefined
|
||||
modelType = undefined
|
||||
context.options.onError(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||
|
@ -119,13 +119,13 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
} else if (hasDynamicKeyVBind(node)) {
|
||||
// element has bindings with dynamic keys, which can possibly contain
|
||||
// "type".
|
||||
runtimeDirective = 'vModelDynamic'
|
||||
modelType = 'dynamic'
|
||||
} else {
|
||||
// text type
|
||||
__DEV__ && checkDuplicatedValue()
|
||||
}
|
||||
} else if (tag === 'select') {
|
||||
runtimeDirective = 'vModelSelect'
|
||||
modelType = 'select'
|
||||
} else {
|
||||
// textarea
|
||||
__DEV__ && checkDuplicatedValue()
|
||||
|
@ -139,6 +139,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
)
|
||||
}
|
||||
|
||||
// TODO this should no longer be needed
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.SET_MODEL_VALUE,
|
||||
element: context.reference(),
|
||||
|
@ -147,12 +148,13 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
isComponent,
|
||||
})
|
||||
|
||||
if (runtimeDirective)
|
||||
if (modelType)
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
type: IRNodeTypes.DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir,
|
||||
name: runtimeDirective,
|
||||
name: 'model',
|
||||
modelType,
|
||||
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 { IRNodeTypes } from '../ir'
|
||||
|
||||
|
@ -8,13 +14,24 @@ export const transformVShow: DirectiveTransform = (dir, node, context) => {
|
|||
context.options.onError(
|
||||
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({
|
||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
type: IRNodeTypes.DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir,
|
||||
name: 'vShow',
|
||||
name: 'show',
|
||||
builtin: true,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
import type { ObjectDirective } from '@vue/runtime-core'
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const vShowOriginalDisplay: unique symbol = Symbol('_vod')
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const vShowHidden: unique symbol = Symbol('_vsh')
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface VShowElement extends HTMLElement {
|
||||
// _vod = vue original display
|
||||
[vShowOriginalDisplay]: string
|
||||
|
|
|
@ -322,3 +322,11 @@ export { patchStyle } from './modules/style'
|
|||
* @internal
|
||||
*/
|
||||
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'
|
||||
export { createTemplateRefSetter } from './apiTemplateRef'
|
||||
export { createDynamicComponent } from './apiCreateDynamicComponent'
|
||||
export { applyVShow } from './directives/vShow'
|
||||
|
|
Loading…
Reference in New Issue