Skip to content

Commit 7a52104

Browse files
nickmessing张祥闰
authored and
张祥闰
committed
fix(vdom): Don't replace input for text-like type change (vuejs#6344)
fix vuejs#6313
1 parent b5afbc0 commit 7a52104

File tree

4 files changed

+32
-8
lines changed

4 files changed

+32
-8
lines changed

src/core/vdom/patch.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
*
77
* modified by Evan You (@yyx990803)
88
*
9-
10-
/*
119
* Not type-checking this because this file is perf-critical and the cost
1210
* of making flow understand it is not worth it.
1311
*/
@@ -17,6 +15,7 @@ import config from '../config'
1715
import { SSR_ATTR } from 'shared/constants'
1816
import { registerRef } from './modules/ref'
1917
import { activeInstance } from '../instance/lifecycle'
18+
import { isTextInputType } from 'web/util/element'
2019

2120
import {
2221
warn,
@@ -48,14 +47,12 @@ function sameVnode (a, b) {
4847
)
4948
}
5049

51-
// Some browsers do not support dynamically changing type for <input>
52-
// so they need to be treated as different nodes
5350
function sameInputType (a, b) {
5451
if (a.tag !== 'input') return true
5552
let i
5653
const typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type
5754
const typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type
58-
return typeA === typeB
55+
return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB)
5956
}
6057

6158
function createKeyToOldIdx (children, beginIdx, endIdx) {

src/platforms/web/runtime/directives/model.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
* properties to Elements.
44
*/
55

6-
import { looseEqual, looseIndexOf, makeMap } from 'shared/util'
6+
import { isTextInputType } from 'web/util/element'
7+
import { looseEqual, looseIndexOf } from 'shared/util'
78
import { warn, isAndroid, isIE9, isIE, isEdge } from 'core/util/index'
89

9-
const isTextInputType = makeMap('text,number,password,search,email,tel,url')
10-
1110
/* istanbul ignore if */
1211
if (isIE9) {
1312
// http://www.matts411.com/post/internet-explorer-9-oninput/

src/platforms/web/util/element.js

+2
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,5 @@ export function isUnknownElement (tag: string): boolean {
7373
return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString()))
7474
}
7575
}
76+
77+
export const isTextInputType = makeMap('text,number,password,search,email,tel,url')

test/unit/modules/vdom/patch/edge-cases.spec.js

+26
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,30 @@ describe('vdom patch: edge cases', () => {
135135
expect(vm.$el.children[0].value).toBe('a')
136136
}).then(done)
137137
})
138+
139+
// #6313
140+
it('should not replace node when switching between text-like inputs', done => {
141+
const vm = new Vue({
142+
data: { show: false },
143+
template: `
144+
<div>
145+
<input :type="show ? 'text' : 'password'">
146+
</div>
147+
`
148+
}).$mount()
149+
const node = vm.$el.children[0]
150+
expect(vm.$el.children[0].type).toBe('password')
151+
vm.$el.children[0].value = 'test'
152+
vm.show = true
153+
waitForUpdate(() => {
154+
expect(vm.$el.children[0]).toBe(node)
155+
expect(vm.$el.children[0].value).toBe('test')
156+
expect(vm.$el.children[0].type).toBe('text')
157+
vm.show = false
158+
}).then(() => {
159+
expect(vm.$el.children[0]).toBe(node)
160+
expect(vm.$el.children[0].value).toBe('test')
161+
expect(vm.$el.children[0].type).toBe('password')
162+
}).then(done)
163+
})
138164
})

0 commit comments

Comments
 (0)