Skip to content

Commit

Permalink
fix(v-model): avoid duplicate model transforms
Browse files Browse the repository at this point in the history
This happens when a component directly passes down its own data object
to a child component. Fix vuejs#8436.
  • Loading branch information
yyx990803 authored and aJean committed Aug 19, 2020
1 parent 839f2db commit 544275f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 3 deletions.
14 changes: 11 additions & 3 deletions src/core/vdom/create-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
56 changes: 56 additions & 0 deletions test/unit/features/directives/model-component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: `
<div>
<functional-wrapper v-model="val"/>
</div>
`,
data: {
internalVal: ''
},
computed: {
val: {
get () {
return this.internalVal
},
set (val) {
triggerCount++
this.internalVal = val
}
}
}
}).$mount()

document.body.appendChild(vm.$el)
triggerEvent(vm.$el.querySelector('input'), 'input')
expect(triggerCount).toBe(1)
document.body.removeChild(vm.$el)
})
})

0 comments on commit 544275f

Please sign in to comment.