diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index 697afbefb22..b769fa1e19d 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -252,9 +252,17 @@ function transformModel (options, data: any) { const event = (options.model && options.model.event) || 'input' ;(data.props || (data.props = {}))[prop] = data.model.value const on = data.on || (data.on = {}) - if (isDef(on[event])) { - on[event] = [data.model.callback].concat(on[event]) + const existing = on[event] + const callback = data.model.callback + if (isDef(existing)) { + if ( + Array.isArray(existing) + ? existing.indexOf(callback) === -1 + : existing !== callback + ) { + on[event] = [callback].concat(existing) + } } else { - on[event] = data.model.callback + on[event] = callback } } diff --git a/test/unit/features/directives/model-component.spec.js b/test/unit/features/directives/model-component.spec.js index 6098e4d6241..9f9536ada09 100644 --- a/test/unit/features/directives/model-component.spec.js +++ b/test/unit/features/directives/model-component.spec.js @@ -148,4 +148,60 @@ describe('Directive v-model component', () => { vm.$refs.input.$emit('input', ' foo o ') expect(vm.text).toBe('foo o') }) + + // #8436 + it('should not double transform mode props', () => { + const BaseInput = { + props: ['value'], + render (h) { + return h('input', { + domProps: { + value: this.value + }, + on: { + input: e => this.$emit('input', e.target.value) + } + }) + } + } + + const FunctionalWrapper = { + functional: true, + render (h, ctx) { + return h(BaseInput, ctx.data) + } + } + + let triggerCount = 0 + + const vm = new Vue({ + components: { + FunctionalWrapper + }, + template: ` +