diff --git a/src/compiler/parser/index.ts b/src/compiler/parser/index.ts index 148cc0110f5..3c3627249a8 100644 --- a/src/compiler/parser/index.ts +++ b/src/compiler/parser/index.ts @@ -3,7 +3,7 @@ import { parseHTML } from './html-parser' import { parseText } from './text-parser' import { parseFilters } from './filter-parser' import { genAssignmentCode } from '../directives/model' -import { extend, cached, no, camelize, hyphenate } from 'shared/util' +import { extend, cached, no, camelize, hyphenate, makeMap } from 'shared/util' import { isIE, isEdge, isServerRendering } from 'core/util/env' import { @@ -50,6 +50,9 @@ const whitespaceRE = /[ \f\t\r\n]+/g const invalidAttributeRE = /[\s"'<>\/=]/ const decodeHTMLCached = cached(he.decode) +const isBuiltInDirective = makeMap( + 'bind,cloak,else,else-if,for,html,if,model,on,once,pre,show,slot,text' +) export const emptySlotScopeToken = `_empty_` @@ -791,6 +794,9 @@ function processAttrs(el) { if (bindRE.test(name)) { // v-bind name = name.replace(bindRE, '') + if (__DEV__) { + warnIfDirectiveBinding(rawName, name, list[i]) + } value = parseFilters(value) isDynamic = dynamicArgRE.test(name) if (isDynamic) { @@ -858,6 +864,9 @@ function processAttrs(el) { } else if (onRE.test(name)) { // v-on name = name.replace(onRE, '') + if (__DEV__) { + warnIfDirectiveBinding(rawName, name, list[i]) + } isDynamic = dynamicArgRE.test(name) if (isDynamic) { name = name.slice(1, -1) @@ -919,6 +928,17 @@ function processAttrs(el) { } } +function warnIfDirectiveBinding(rawName: string, name: string, range?: any) { + const directiveName = name.replace(/^v-/, '') + if (isBuiltInDirective(directiveName)) { + warn( + `"${rawName}" does not make sense on directive "v-${directiveName}". ` + + `Did you mean "v-${directiveName}"?`, + range + ) + } +} + function checkInFor(el: ASTElement): boolean { let parent: ASTElement | void = el while (parent) { diff --git a/test/unit/modules/compiler/parser.spec.ts b/test/unit/modules/compiler/parser.spec.ts index 1efba124146..f84d5d5880f 100644 --- a/test/unit/modules/compiler/parser.spec.ts +++ b/test/unit/modules/compiler/parser.spec.ts @@ -555,6 +555,18 @@ describe('parser', () => { expect(ast.ifConditions[0].exp).toBe('show') }) + it('warn directive used with v-bind or v-on shorthand', () => { + parse('
hello world
', baseOptions) + expect( + '":v-if" does not make sense on directive "v-if". Did you mean "v-if"?' + ).toHaveBeenWarned() + + parse('hello world
', baseOptions) + expect( + '"@v-html" does not make sense on directive "v-html". Did you mean "v-html"?' + ).toHaveBeenWarned() + }) + it('v-else-if directive syntax', () => { const ast = parse( 'hello
elseifworld