/
props.ts
105 lines (99 loc) 路 2.8 KB
/
props.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
// __UNSAFE__
// Reason: potentially setting innerHTML.
// This can come from explicit usage of v-html or innerHTML as a prop in render
import { warn, DeprecationTypes, compatUtils } from '@vue/runtime-core'
import { includeBooleanAttr } from '@vue/shared'
// functions. The user is responsible for using them with only trusted content.
export function patchDOMProp(
el: any,
key: string,
value: any,
// the following args are passed only due to potential innerHTML/textContent
// overriding existing VNodes, in which case the old tree must be properly
// unmounted.
prevChildren: any,
parentComponent: any,
parentSuspense: any,
unmountChildren: any
) {
if (key === 'innerHTML' || key === 'textContent') {
if (prevChildren) {
unmountChildren(prevChildren, parentComponent, parentSuspense)
}
el[key] = value == null ? '' : value
return
}
if (key === 'value' && el.tagName !== 'PROGRESS') {
// store value as _value as well since
// non-string values will be stringified.
el._value = value
const newValue = value == null ? '' : value
if (
el.value !== newValue ||
// #4956: always set for OPTION elements because its value falls back to
// textContent if no value attribute is present. And setting .value for
// OPTION has no side effect
el.tagName === 'OPTION'
) {
el.value = newValue
}
if (value == null) {
el.removeAttribute(key)
}
return
}
if (value === '' || value == null) {
const type = typeof el[key]
if (type === 'boolean') {
// e.g. <select multiple> compiles to { multiple: '' }
el[key] = includeBooleanAttr(value)
return
} else if (value == null && type === 'string') {
// e.g. <div :id="null">
el[key] = ''
el.removeAttribute(key)
return
} else if (type === 'number') {
// e.g. <img :width="null">
// the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
try {
el[key] = 0
} catch {}
el.removeAttribute(key)
return
}
}
if (
__COMPAT__ &&
value === false &&
compatUtils.isCompatEnabled(
DeprecationTypes.ATTR_FALSE_VALUE,
parentComponent
)
) {
const type = typeof el[key]
if (type === 'string' || type === 'number') {
__DEV__ &&
compatUtils.warnDeprecation(
DeprecationTypes.ATTR_FALSE_VALUE,
parentComponent,
key
)
el[key] = type === 'number' ? 0 : ''
el.removeAttribute(key)
return
}
}
// some properties perform value validation and throw
try {
el[key] = value
} catch (e: any) {
if (__DEV__) {
warn(
`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` +
`value ${value} is invalid.`,
e
)
}
}
}