fix(v-model): allow v-model usage on declared custom elements

fix #1699
This commit is contained in:
Evan You 2020-07-27 17:09:21 -04:00
parent 2a633c84ff
commit 71c3c6e2a0
5 changed files with 43 additions and 3 deletions

View File

@ -28,7 +28,7 @@ export interface ParserOptions {
/**
* Separate option for end users to extend the native elements list
*/
isCustomElement?: (tag: string) => boolean
isCustomElement?: (tag: string) => boolean | void
/**
* Get tag namespace
*/
@ -83,6 +83,10 @@ export interface TransformOptions {
* for them.
*/
isBuiltInComponent?: (tag: string) => symbol | void
/**
* Used by some transforms that expects only native elements
*/
isCustomElement?: (tag: string) => boolean | void
/**
* Transform expressions like {{ foo }} to `_ctx.foo`.
* If this option is false, the generated code will be wrapped in a

View File

@ -117,6 +117,7 @@ export function createTransformContext(
directiveTransforms = {},
transformHoist = null,
isBuiltInComponent = NOOP,
isCustomElement = NOOP,
expressionPlugins = [],
scopeId = null,
ssr = false,
@ -134,6 +135,7 @@ export function createTransformContext(
directiveTransforms,
transformHoist,
isBuiltInComponent,
isCustomElement,
expressionPlugins,
scopeId,
ssr,

View File

@ -1,5 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`compiler: transform v-model errors should allow custom element 1`] = `
"const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { vModelText: _vModelText, createVNode: _createVNode, withDirectives: _withDirectives, openBlock: _openBlock, createBlock: _createBlock } = _Vue
return _withDirectives((_openBlock(), _createBlock(\\"my-input\\", {
\\"onUpdate:modelValue\\": $event => (model = $event)
}, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [
[_vModelText, model]
])
}
}"
`;
exports[`compiler: transform v-model input w/ dynamic v-bind 1`] = `
"const _Vue = Vue

View File

@ -115,6 +115,17 @@ describe('compiler: transform v-model', () => {
)
})
test('should allow usage on custom element', () => {
const onError = jest.fn()
const root = transformWithModel('<my-input v-model="model" />', {
onError,
isCustomElement: tag => tag.startsWith('my-')
})
expect(root.helpers).toContain(V_MODEL_TEXT)
expect(onError).not.toHaveBeenCalled()
expect(generate(root).code).toMatchSnapshot()
})
test('should raise error if used file input element', () => {
const onError = jest.fn()
transformWithModel(`<input type="file" v-model="test"/>`, {

View File

@ -44,7 +44,12 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
}
const { tag } = node
if (tag === 'input' || tag === 'textarea' || tag === 'select') {
if (
tag === 'input' ||
tag === 'textarea' ||
tag === 'select' ||
context.isCustomElement(tag)
) {
let directiveToUse = V_MODEL_TEXT
let isInvalidType = false
if (tag === 'input') {
@ -86,7 +91,9 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
}
} else if (tag === 'select') {
directiveToUse = V_MODEL_SELECT
} else if (tag === 'textarea') {
}
{
// textarea or custom elements
__DEV__ && checkDuplicatedValue()
}
// inject runtime directive