diff --git a/src/platforms/web/runtime/directives/model.js b/src/platforms/web/runtime/directives/model.js index a4c0591264d..ee355978421 100644 --- a/src/platforms/web/runtime/directives/model.js +++ b/src/platforms/web/runtime/directives/model.js @@ -30,6 +30,7 @@ export default { if (isIE || isEdge) { setTimeout(cb, 0) } + el._vOptions = [].map.call(el.options, getValue) } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) { el._vModifiers = binding.modifiers if (!binding.modifiers.lazy) { @@ -56,10 +57,9 @@ export default { // it's possible that the value is out-of-sync with the rendered options. // detect such cases and filter out values that no longer has a matching // option in the DOM. - const needReset = el.multiple - ? binding.value.some(v => hasNoMatchingOption(v, el.options)) - : binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, el.options) - if (needReset) { + const prevOptions = el._vOptions + const curOptions = el._vOptions = [].map.call(el.options, getValue) + if (curOptions.some((o, i) => !looseEqual(o, prevOptions[i]))) { trigger(el, 'change') } } @@ -101,15 +101,6 @@ function setSelected (el, binding, vm) { } } -function hasNoMatchingOption (value, options) { - for (let i = 0, l = options.length; i < l; i++) { - if (looseEqual(getValue(options[i]), value)) { - return false - } - } - return true -} - function getValue (option) { return '_value' in option ? option._value diff --git a/test/unit/features/directives/model-select.spec.js b/test/unit/features/directives/model-select.spec.js index 25c55720dee..d188422a626 100644 --- a/test/unit/features/directives/model-select.spec.js +++ b/test/unit/features/directives/model-select.spec.js @@ -471,4 +471,22 @@ describe('Directive v-model select', () => { expect(vm.$el.childNodes[0].selected).toBe(true) }).then(done) }) + + // #6112 + it('should not set non-matching value to undefined if options did not change', done => { + const vm = new Vue({ + data: { + test: '1' + }, + template: + '' + }).$mount() + + vm.test = '2' + waitForUpdate(() => { + expect(vm.test).toBe('2') + }).then(done) + }) })