Skip to content

Commit

Permalink
fix($vdom): Don't replace input for text-like type change
Browse files Browse the repository at this point in the history
  • Loading branch information
nickmessing committed Aug 11, 2017
1 parent c628103 commit 00038cb
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
10 changes: 4 additions & 6 deletions src/core/vdom/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
*
* modified by Evan You (@yyx990803)
*
/*
* Not type-checking this because this file is perf-critical and the cost
* of making flow understand it is not worth it.
*/

import VNode from './vnode'
import config from '../config'
import { SSR_ATTR } from 'shared/constants'
import { SSR_ATTR, TEXT_INPUT_TYPES } from 'shared/constants'
import { registerRef } from './modules/ref'
import { activeInstance } from '../instance/lifecycle'

Expand All @@ -27,6 +25,8 @@ import {
isPrimitive
} from '../util/index'

const isTextInputType = makeMap(TEXT_INPUT_TYPES)

export const emptyNode = new VNode('', {}, [])

const hooks = ['create', 'activate', 'update', 'remove', 'destroy']
Expand All @@ -48,14 +48,12 @@ function sameVnode (a, b) {
)
}

// Some browsers do not support dynamically changing type for <input>
// so they need to be treated as different nodes
function sameInputType (a, b) {
if (a.tag !== 'input') return true
let i
const typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type
const typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type
return typeA === typeB
return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB)
}

function createKeyToOldIdx (children, beginIdx, endIdx) {
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/web/runtime/directives/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
*/

import { looseEqual, looseIndexOf, makeMap } from 'shared/util'
import { TEXT_INPUT_TYPES } from 'shared/constants'
import { warn, isAndroid, isIE9, isIE, isEdge } from 'core/util/index'

const isTextInputType = makeMap('text,number,password,search,email,tel,url')
const isTextInputType = makeMap(TEXT_INPUT_TYPES)

/* istanbul ignore if */
if (isIE9) {
Expand Down
2 changes: 2 additions & 0 deletions src/shared/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export const LIFECYCLE_HOOKS = [
'activated',
'deactivated'
]

export const TEXT_INPUT_TYPES = 'text,number,password,search,email,tel,url'
23 changes: 23 additions & 0 deletions test/unit/modules/vdom/patch/edge-cases.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,27 @@ describe('vdom patch: edge cases', () => {
expect(vm.$el.children[0].value).toBe('a')
}).then(done)
})

// #6313
it('should not replace node when switching between text-like inputs', done => {
const vm = new Vue({
data: { show: false },
template: `
<div>
<input :type="show ? 'text' : 'password'">
</div>
`
}).$mount()
const node = vm.$el.children[0]
vm.$el.children[0].value = 'test'
vm.ok = true
waitForUpdate(() => {
expect(vm.$el.children[0]).toBe(node)
expect(vm.$el.children[0].value).toBe('test')
vm.ok = false
}).then(() => {
expect(vm.$el.children[0]).toBe(node)
expect(vm.$el.children[0].value).toBe('test')
}).then(done)
})
})

0 comments on commit 00038cb

Please sign in to comment.