vue3-core/packages/runtime-dom/src/patchProp.ts

85 lines
2.7 KiB
TypeScript
Raw Normal View History

2018-09-19 23:35:38 +08:00
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 } 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
) => {
2018-09-19 23:35:38 +08:00
switch (key) {
// special
case 'class':
patchClass(el, nextValue, isSVG)
break
case 'style':
patchStyle(el, prevValue, nextValue)
2018-09-19 23:35:38 +08:00
break
default:
2018-10-18 00:20:54 +08:00
if (isOn(key)) {
// ignore v-model listeners
if (!key.startsWith('onUpdate:')) {
patchEvent(el, key, prevValue, nextValue, parentComponent)
}
} else if (
// 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.
key !== 'spellcheck' &&
key !== 'draggable' &&
(isSVG
? // most keys must be set as attribute on svg elements to work
// ...except innerHTML
key === 'innerHTML' ||
// or native onclick with function values
(key in el && nativeOnRE.test(key) && isFunction(nextValue))
: // for normal html elements, set as a property if it exists
key in el &&
// except native onclick with string values
!(nativeOnRE.test(key) && isString(nextValue)))
) {
patchDOMProp(
el,
key,
nextValue,
prevChildren,
parentComponent,
2019-09-11 00:11:08 +08:00
parentSuspense,
unmountChildren
)
2018-09-19 23:35:38 +08:00
} 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
}
2020-01-29 07:48:27 +08:00
patchAttr(el, key, nextValue, isSVG)
2018-09-19 23:35:38 +08:00
}
break
}
}