From d88100e1a679d53b2bd1501e48165fbf52f9befb Mon Sep 17 00:00:00 2001 From: defcc Date: Sat, 17 Dec 2016 10:51:01 +0800 Subject: [PATCH 1/2] update dom prop for option.value --- src/platforms/web/runtime/modules/dom-props.js | 3 ++- test/unit/features/directives/bind.spec.js | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/platforms/web/runtime/modules/dom-props.js b/src/platforms/web/runtime/modules/dom-props.js index ce00db94b74..05f10c18535 100644 --- a/src/platforms/web/runtime/modules/dom-props.js +++ b/src/platforms/web/runtime/modules/dom-props.js @@ -37,7 +37,8 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) { const strCur = cur == null ? '' : String(cur) if (!elm.composing && ( (document.activeElement !== elm && elm.value !== strCur) || - isValueChanged(vnode, strCur) + isValueChanged(vnode, strCur) || + elm.tagName.toLowerCase() === 'option' )) { elm.value = strCur } diff --git a/test/unit/features/directives/bind.spec.js b/test/unit/features/directives/bind.spec.js index 5635778569c..b35a05d65c4 100644 --- a/test/unit/features/directives/bind.spec.js +++ b/test/unit/features/directives/bind.spec.js @@ -248,6 +248,17 @@ describe('Directive v-bind', () => { expect('v-bind without argument expects an Object or Array value').toHaveBeenWarned() }) + it('set value for option element', () => { + const vm = new Vue({ + template: '', + data: { + val: 'val' + } + }).$mount() + // check value attribute + expect(vm.$el.options[0].getAttribute('value')).toBe('val') + }) + // a vdom patch edge case where the user has several un-keyed elements of the // same tag next to each other, and toggling them. it('properly update for toggling un-keyed children', done => { From f0fc883205adc413334152da5dedc0bc274f0ed9 Mon Sep 17 00:00:00 2001 From: defcc Date: Sat, 17 Dec 2016 11:27:49 +0800 Subject: [PATCH 2/2] refactor value update logic --- .../web/runtime/modules/dom-props.js | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/platforms/web/runtime/modules/dom-props.js b/src/platforms/web/runtime/modules/dom-props.js index 05f10c18535..b322aae0929 100644 --- a/src/platforms/web/runtime/modules/dom-props.js +++ b/src/platforms/web/runtime/modules/dom-props.js @@ -2,6 +2,9 @@ import { extend, toNumber } from 'shared/util' +// check platforms/web/util/attrs.js acceptValue +declare type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement + function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) { if (!oldVnode.data.domProps && !vnode.data.domProps) { return @@ -35,11 +38,7 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) { elm._value = cur // avoid resetting cursor position when value is the same const strCur = cur == null ? '' : String(cur) - if (!elm.composing && ( - (document.activeElement !== elm && elm.value !== strCur) || - isValueChanged(vnode, strCur) || - elm.tagName.toLowerCase() === 'option' - )) { + if (needUpdateValue(elm, vnode, strCur)) { elm.value = strCur } } else { @@ -48,7 +47,20 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) { } } -function isValueChanged (vnode: VNodeWithData, newVal: string): boolean { +function needUpdateValue (elm: acceptValueElm, vnode: VNodeWithData, checkVal: string): boolean { + // inputing + if (elm.composing) return false + if (elm.tagName.toLowerCase() === 'option') return true + if (isDirty(elm, checkVal)) return true + if (isInputChanged(vnode, checkVal)) return true + return false +} + +function isDirty (elm: acceptValueElm, checkVal: string): boolean { + return document.activeElement !== elm && elm.value !== checkVal +} + +function isInputChanged (vnode: VNodeWithData, newVal: string): boolean { const value = vnode.elm.value const modifiers = vnode.elm._vModifiers // injected by v-model runtime if ((modifiers && modifiers.number) || vnode.elm.type === 'number') {