Browse Source

ensure v-model to have higher priority than v-on events (fix #3468)

dev
Evan You 8 years ago
parent
commit
e62165ca89
  1. 7
      src/compiler/helpers.js
  2. 9
      src/platforms/web/compiler/directives/model.js
  3. 19
      test/unit/features/directives/model-text.spec.js

7
src/compiler/helpers.js

@ -46,7 +46,8 @@ export function addHandler (
el: ASTElement,
name: string,
value: string,
modifiers: ?{ [key: string]: true }
modifiers: ?{ [key: string]: true },
important: ?boolean
) {
// check capture modifier
if (modifiers && modifiers.capture) {
@ -64,9 +65,9 @@ export function addHandler (
const handlers = events[name]
/* istanbul ignore if */
if (Array.isArray(handlers)) {
handlers.push(newHandler)
important ? handlers.unshift(newHandler) : handlers.push(newHandler)
} else if (handlers) {
events[name] = [handlers, newHandler]
events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
} else {
events[name] = newHandler
}

9
src/platforms/web/compiler/directives/model.js

@ -55,7 +55,8 @@ function genCheckboxModel (el: ASTElement, value: ?string) {
'$$i=$$a.indexOf($$v);' +
`if($$c){$$i<0&&(${value}=$$a.concat($$v))}` +
`else{$$i>-1&&(${value}=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}` +
`}else{${value}=$$c}`
`}else{${value}=$$c}`,
null, true
)
}
@ -70,7 +71,7 @@ function genRadioModel (el: ASTElement, value: ?string) {
}
const valueBinding = getBindingAttr(el, 'value')
addProp(el, 'checked', `(${value})===(${valueBinding})`)
addHandler(el, 'change', `${value}=${valueBinding}`)
addHandler(el, 'change', `${value}=${valueBinding}`, null, true)
}
function genDefaultModel (
@ -111,7 +112,7 @@ function genDefaultModel (
code = `if($event.target.composing)return;${code}`
}
addProp(el, 'value', isNative ? `_s(${value})` : `(${value})`)
addHandler(el, event, code)
addHandler(el, event, code, null, true)
if (needCompositionGuard) {
// need runtime directive code to help with composition events
return true
@ -126,7 +127,7 @@ function genSelect (el: ASTElement, value: ?string) {
`.call($event.target.options,function(o){return o.selected})` +
`.map(function(o){return "_value" in o ? o._value : o.value})` +
(el.attrsMap.multiple == null ? '[0]' : '')
addHandler(el, 'change', code)
addHandler(el, 'change', code, null, true)
// need runtime to help with possible dynamically generated options
return true
}

19
test/unit/features/directives/model-text.spec.js

@ -141,4 +141,23 @@ describe('Directive v-model text', () => {
}).$mount()
expect('v-model is not supported on element type: <div>').toHaveBeenWarned()
})
// #3468
it('should have higher priority than user v-on events', () => {
const spy = jasmine.createSpy()
const vm = new Vue({
data: {
a: 'a'
},
template: '<input v-model="a" @input="onInput">',
methods: {
onInput (e) {
spy(e.target.value)
}
}
}).$mount()
vm.$el.value = 'b'
triggerEvent(vm.$el, 'input')
expect(spy).toHaveBeenCalledWith('b')
})
})

Loading…
Cancel
Save