wip(compiler-dom): v-model runtime
This commit is contained in:
@@ -24,12 +24,16 @@ export const enum DOMErrorCodes {
|
||||
X_V_HTML_NO_EXPRESSION = ErrorCodes.__EXTEND_POINT__,
|
||||
X_V_HTML_WITH_CHILDREN,
|
||||
X_V_TEXT_NO_EXPRESSION,
|
||||
X_V_TEXT_WITH_CHILDREN
|
||||
X_V_TEXT_WITH_CHILDREN,
|
||||
X_V_MODEL_ON_INVALID_ELEMENT,
|
||||
X_V_MODEL_ARG_ON_ELEMENT
|
||||
}
|
||||
|
||||
export const DOMErrorMessages: { [code: number]: string } = {
|
||||
[DOMErrorCodes.X_V_HTML_NO_EXPRESSION]: `v-html is missing expression.`,
|
||||
[DOMErrorCodes.X_V_HTML_WITH_CHILDREN]: `v-html will override element children.`,
|
||||
[DOMErrorCodes.X_V_TEXT_NO_EXPRESSION]: `v-text is missing expression.`,
|
||||
[DOMErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`
|
||||
[DOMErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`,
|
||||
[DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
|
||||
[DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT]: `v-model argument is not supported on plain elements.`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { transformStyle } from './transforms/transformStyle'
|
||||
import { transformCloak } from './transforms/vCloak'
|
||||
import { transformVHtml } from './transforms/vHtml'
|
||||
import { transformVText } from './transforms/vText'
|
||||
import { transformModel } from './transforms/vModel'
|
||||
|
||||
export function compile(
|
||||
template: string,
|
||||
@@ -18,6 +19,7 @@ export function compile(
|
||||
cloak: transformCloak,
|
||||
html: transformVHtml,
|
||||
text: transformVText,
|
||||
model: transformModel, // override compiler-core
|
||||
...(options.directiveTransforms || {})
|
||||
}
|
||||
})
|
||||
|
||||
15
packages/compiler-dom/src/runtimeHelpers.ts
Normal file
15
packages/compiler-dom/src/runtimeHelpers.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { registerRuntimeHelpers } from '@vue/compiler-core'
|
||||
|
||||
export const V_MODEL_RADIO = Symbol(__DEV__ ? `vModelRadio` : ``)
|
||||
export const V_MODEL_CHECKBOX = Symbol(__DEV__ ? `vModelCheckbox` : ``)
|
||||
export const V_MODEL_TEXT = Symbol(__DEV__ ? `vModelText` : ``)
|
||||
export const V_MODEL_SELECT = Symbol(__DEV__ ? `vModelSelect` : ``)
|
||||
export const V_MODEL_DYNAMIC = Symbol(__DEV__ ? `vModelDynamic` : ``)
|
||||
|
||||
registerRuntimeHelpers({
|
||||
[V_MODEL_RADIO]: `vModelRadio`,
|
||||
[V_MODEL_CHECKBOX]: `vModelCheckbox`,
|
||||
[V_MODEL_TEXT]: `vModelText`,
|
||||
[V_MODEL_SELECT]: `vModelSelect`,
|
||||
[V_MODEL_DYNAMIC]: `vModelDynamic`
|
||||
})
|
||||
@@ -19,10 +19,12 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
||||
node.children.length = 0
|
||||
}
|
||||
return {
|
||||
props: createObjectProperty(
|
||||
createSimpleExpression(`innerHTML`, true, loc),
|
||||
exp || createSimpleExpression('', true)
|
||||
),
|
||||
props: [
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`innerHTML`, true, loc),
|
||||
exp || createSimpleExpression('', true)
|
||||
)
|
||||
],
|
||||
needRuntime: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,66 @@
|
||||
// TODO
|
||||
import {
|
||||
transformModel as baseTransform,
|
||||
DirectiveTransform,
|
||||
ElementTypes,
|
||||
findProp,
|
||||
NodeTypes
|
||||
} from '@vue/compiler-core'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import {
|
||||
V_MODEL_CHECKBOX,
|
||||
V_MODEL_RADIO,
|
||||
V_MODEL_SELECT,
|
||||
V_MODEL_TEXT,
|
||||
V_MODEL_DYNAMIC
|
||||
} from '../runtimeHelpers'
|
||||
|
||||
export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
const res = baseTransform(dir, node, context)
|
||||
const { tag, tagType } = node
|
||||
if (tagType === ElementTypes.ELEMENT) {
|
||||
if (dir.arg) {
|
||||
context.onError(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
|
||||
dir.arg.loc
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (tag === 'input' || tag === 'textarea' || tag === 'select') {
|
||||
let directiveToUse = V_MODEL_TEXT
|
||||
if (tag === 'input') {
|
||||
const type = findProp(node, `type`)
|
||||
if (type) {
|
||||
if (type.type === NodeTypes.DIRECTIVE) {
|
||||
// :type="foo"
|
||||
directiveToUse = V_MODEL_DYNAMIC
|
||||
} else if (type.value) {
|
||||
switch (type.value.content) {
|
||||
case 'radio':
|
||||
directiveToUse = V_MODEL_RADIO
|
||||
break
|
||||
case 'checkbox':
|
||||
directiveToUse = V_MODEL_CHECKBOX
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tag === 'select') {
|
||||
directiveToUse = V_MODEL_SELECT
|
||||
}
|
||||
// inject runtime directive
|
||||
// by returning the helper symbol via needRuntime
|
||||
// the import will replaced a resovleDirective call.
|
||||
res.needRuntime = context.helper(directiveToUse)
|
||||
} else {
|
||||
context.onError(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
|
||||
dir.loc
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
|
||||
node.children.length = 0
|
||||
}
|
||||
return {
|
||||
props: createObjectProperty(
|
||||
createSimpleExpression(`textContent`, true, loc),
|
||||
exp || createSimpleExpression('', true)
|
||||
),
|
||||
props: [
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`textContent`, true, loc),
|
||||
exp || createSimpleExpression('', true)
|
||||
)
|
||||
],
|
||||
needRuntime: false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user