dom-props.js
2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* @flow */
import { extend, toNumber } from 'shared/util'
function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
if (!oldVnode.data.domProps && !vnode.data.domProps) {
return
}
let key, cur
const elm: any = vnode.elm
const oldProps = oldVnode.data.domProps || {}
let props = vnode.data.domProps || {}
// clone observed objects, as the user probably wants to mutate it
if (props.__ob__) {
props = vnode.data.domProps = extend({}, props)
}
for (key in oldProps) {
if (props[key] == null) {
elm[key] = ''
}
}
for (key in props) {
cur = props[key]
// ignore children if the node has textContent or innerHTML,
// as these will throw away existing DOM nodes and cause removal errors
// on subsequent patches (#3360)
if (key === 'textContent' || key === 'innerHTML') {
if (vnode.children) vnode.children.length = 0
if (cur === oldProps[key]) continue
}
if (key === 'value') {
// store value as _value as well since
// non-string values will be stringified
elm._value = cur
// avoid resetting cursor position when value is the same
const strCur = cur == null ? '' : String(cur)
if (shouldUpdateValue(elm, vnode, strCur)) {
elm.value = strCur
}
} else {
elm[key] = cur
}
}
}
// check platforms/web/util/attrs.js acceptValue
type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement
function shouldUpdateValue (
elm: acceptValueElm,
vnode: VNodeWithData,
checkVal: string
): boolean {
return (!elm.composing && (
vnode.tag === 'option' ||
isDirty(elm, checkVal) ||
isInputChanged(vnode, checkVal)
))
}
function isDirty (elm: acceptValueElm, checkVal: string): boolean {
// return true when textbox (.number and .trim) loses focus and its value is not equal to the updated value
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') {
return toNumber(value) !== toNumber(newVal)
}
if (modifiers && modifiers.trim) {
return value.trim() !== newVal.trim()
}
return value !== newVal
}
export default {
create: updateDOMProps,
update: updateDOMProps
}