Skip to content

Commit e62165c

Browse files
committed
ensure v-model to have higher priority than v-on events (fix #3468)
1 parent 1e74675 commit e62165c

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

src/compiler/helpers.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export function addHandler (
4646
el: ASTElement,
4747
name: string,
4848
value: string,
49-
modifiers: ?{ [key: string]: true }
49+
modifiers: ?{ [key: string]: true },
50+
important: ?boolean
5051
) {
5152
// check capture modifier
5253
if (modifiers && modifiers.capture) {
@@ -64,9 +65,9 @@ export function addHandler (
6465
const handlers = events[name]
6566
/* istanbul ignore if */
6667
if (Array.isArray(handlers)) {
67-
handlers.push(newHandler)
68+
important ? handlers.unshift(newHandler) : handlers.push(newHandler)
6869
} else if (handlers) {
69-
events[name] = [handlers, newHandler]
70+
events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
7071
} else {
7172
events[name] = newHandler
7273
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ function genCheckboxModel (el: ASTElement, value: ?string) {
5555
'$$i=$$a.indexOf($$v);' +
5656
`if($$c){$$i<0&&(${value}=$$a.concat($$v))}` +
5757
`else{$$i>-1&&(${value}=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}` +
58-
`}else{${value}=$$c}`
58+
`}else{${value}=$$c}`,
59+
null, true
5960
)
6061
}
6162

@@ -70,7 +71,7 @@ function genRadioModel (el: ASTElement, value: ?string) {
7071
}
7172
const valueBinding = getBindingAttr(el, 'value')
7273
addProp(el, 'checked', `(${value})===(${valueBinding})`)
73-
addHandler(el, 'change', `${value}=${valueBinding}`)
74+
addHandler(el, 'change', `${value}=${valueBinding}`, null, true)
7475
}
7576

7677
function genDefaultModel (
@@ -111,7 +112,7 @@ function genDefaultModel (
111112
code = `if($event.target.composing)return;${code}`
112113
}
113114
addProp(el, 'value', isNative ? `_s(${value})` : `(${value})`)
114-
addHandler(el, event, code)
115+
addHandler(el, event, code, null, true)
115116
if (needCompositionGuard) {
116117
// need runtime directive code to help with composition events
117118
return true
@@ -126,7 +127,7 @@ function genSelect (el: ASTElement, value: ?string) {
126127
`.call($event.target.options,function(o){return o.selected})` +
127128
`.map(function(o){return "_value" in o ? o._value : o.value})` +
128129
(el.attrsMap.multiple == null ? '[0]' : '')
129-
addHandler(el, 'change', code)
130+
addHandler(el, 'change', code, null, true)
130131
// need runtime to help with possible dynamically generated options
131132
return true
132133
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,23 @@ describe('Directive v-model text', () => {
141141
}).$mount()
142142
expect('v-model is not supported on element type: <div>').toHaveBeenWarned()
143143
})
144+
145+
// #3468
146+
it('should have higher priority than user v-on events', () => {
147+
const spy = jasmine.createSpy()
148+
const vm = new Vue({
149+
data: {
150+
a: 'a'
151+
},
152+
template: '<input v-model="a" @input="onInput">',
153+
methods: {
154+
onInput (e) {
155+
spy(e.target.value)
156+
}
157+
}
158+
}).$mount()
159+
vm.$el.value = 'b'
160+
triggerEvent(vm.$el, 'input')
161+
expect(spy).toHaveBeenCalledWith('b')
162+
})
144163
})

0 commit comments

Comments
 (0)