-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
/
patchProp.ts
113 lines (103 loc) · 3.06 KB
/
patchProp.ts
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { patchClass } from './modules/class'
import { patchStyle } from './modules/style'
import { patchAttr } from './modules/attrs'
import { patchDOMProp } from './modules/props'
import { patchEvent } from './modules/events'
import { isOn, isString, isFunction, isModelListener } from '@vue/shared'
import { RendererOptions } from '@vue/runtime-core'
const nativeOnRE = /^on[a-z]/
type DOMRendererOptions = RendererOptions<Node, Element>
export const forcePatchProp: DOMRendererOptions['forcePatchProp'] = (_, key) =>
key === 'value'
export const patchProp: DOMRendererOptions['patchProp'] = (
el,
key,
prevValue,
nextValue,
isSVG = false,
prevChildren,
parentComponent,
parentSuspense,
unmountChildren
) => {
switch (key) {
// special
case 'class':
patchClass(el, nextValue, isSVG)
break
case 'style':
patchStyle(el, prevValue, nextValue)
break
default:
if (isOn(key)) {
// ignore v-model listeners
if (!isModelListener(key)) {
patchEvent(el, key, prevValue, nextValue, parentComponent)
}
} else if (shouldSetAsProp(el, key, nextValue, isSVG)) {
patchDOMProp(
el,
key,
nextValue,
prevChildren,
parentComponent,
parentSuspense,
unmountChildren
)
} else {
// special case for <input v-model type="checkbox"> with
// :true-value & :false-value
// store value as dom properties since non-string values will be
// stringified.
if (key === 'true-value') {
;(el as any)._trueValue = nextValue
} else if (key === 'false-value') {
;(el as any)._falseValue = nextValue
}
patchAttr(el, key, nextValue, isSVG)
}
break
}
}
function shouldSetAsProp(
el: Element,
key: string,
value: unknown,
isSVG: boolean
) {
if (isSVG) {
// most keys must be set as attribute on svg elements to work
// ...except innerHTML
if (key === 'innerHTML') {
return true
}
// or native onclick with function values
if (key in el && nativeOnRE.test(key) && isFunction(value)) {
return true
}
return false
}
// spellcheck and draggable are numerated attrs, however their
// corresponding DOM properties are actually booleans - this leads to
// setting it with a string "false" value leading it to be coerced to
// `true`, so we need to always treat them as attributes.
// Note that `contentEditable` doesn't have this problem: its DOM
// property is also enumerated string values.
if (key === 'spellcheck' || key === 'draggable') {
return false
}
// #1787 form as an attribute must be a string, while it accepts an Element as
// a prop
if (key === 'form' && typeof value === 'string') {
return false
}
// #1526 <input list> must be set as attribute
if (key === 'list' && el.tagName === 'INPUT') {
return false
}
// native onclick with string value, must be set as attribute
if (nativeOnRE.test(key) && isString(value)) {
return false
}
return key in el
}