| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- 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
- }
|