From b3536d87a587dc1e78c8712cb29ca61ca0931ac9 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 30 Jun 2020 11:23:09 -0400 Subject: [PATCH] fix(runtime-dom): allow force updating value bindings for controlled inputs fix #1471 --- packages/runtime-core/src/renderer.ts | 12 ++++++++++-- packages/runtime-dom/src/directives/vModel.ts | 5 +---- packages/runtime-dom/src/index.ts | 4 ++-- packages/runtime-dom/src/patchProp.ts | 7 ++++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 4dfc2ab6..4b6785ea 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -96,6 +96,7 @@ export interface RendererOptions< parentSuspense?: SuspenseBoundary | null, unmountChildren?: UnmountChildrenFn ): void + forcePatchProp?(el: HostElement, key: string): boolean insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void remove(el: HostNode): void createElement( @@ -383,6 +384,7 @@ function baseCreateRenderer( insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, + forcePatchProp: hostForcePatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, @@ -845,7 +847,10 @@ function baseCreateRenderer( const key = propsToUpdate[i] const prev = oldProps[key] const next = newProps[key] - if (prev !== next) { + if ( + next !== prev || + (hostForcePatchProp && hostForcePatchProp(el, key)) + ) { hostPatchProp( el, key, @@ -969,7 +974,10 @@ function baseCreateRenderer( if (isReservedProp(key)) continue const next = newProps[key] const prev = oldProps[key] - if (next !== prev) { + if ( + next !== prev || + (hostForcePatchProp && hostForcePatchProp(el, key)) + ) { hostPatchProp( el, key, diff --git a/packages/runtime-dom/src/directives/vModel.ts b/packages/runtime-dom/src/directives/vModel.ts index 2caab0a7..34008ecc 100644 --- a/packages/runtime-dom/src/directives/vModel.ts +++ b/packages/runtime-dom/src/directives/vModel.ts @@ -75,11 +75,8 @@ export const vModelText: ModelDirective< addEventListener(el, 'change', onCompositionEnd) } }, - beforeUpdate(el, { value, oldValue, modifiers: { trim, number } }, vnode) { + beforeUpdate(el, { value, modifiers: { trim, number } }, vnode) { el._assign = getModelAssigner(vnode) - if (value === oldValue) { - return - } if (document.activeElement === el) { if (trim && el.value.trim() === value) { return diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index 0dbdd846..89a87c3e 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -10,7 +10,7 @@ import { RootHydrateFunction } from '@vue/runtime-core' import { nodeOps } from './nodeOps' -import { patchProp } from './patchProp' +import { patchProp, forcePatchProp } from './patchProp' // Importing from the compiler, will be tree-shaken in prod import { isFunction, isString, isHTMLTag, isSVGTag, extend } from '@vue/shared' @@ -21,7 +21,7 @@ declare module '@vue/reactivity' { } } -const rendererOptions = extend({ patchProp }, nodeOps) +const rendererOptions = extend({ patchProp, forcePatchProp }, nodeOps) // lazy create the renderer - this makes core renderer logic tree-shakable // in case the user only imports reactivity utilities from Vue. diff --git a/packages/runtime-dom/src/patchProp.ts b/packages/runtime-dom/src/patchProp.ts index 4aa8c010..bd30e8aa 100644 --- a/packages/runtime-dom/src/patchProp.ts +++ b/packages/runtime-dom/src/patchProp.ts @@ -8,7 +8,12 @@ import { RendererOptions } from '@vue/runtime-core' const nativeOnRE = /^on[a-z]/ -export const patchProp: RendererOptions['patchProp'] = ( +type DOMRendererOptions = RendererOptions + +export const forcePatchProp: DOMRendererOptions['forcePatchProp'] = (_, key) => + key === 'value' + +export const patchProp: DOMRendererOptions['patchProp'] = ( el, key, prevValue,