| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- 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 {
- camelize,
- isFunction,
- isModelListener,
- isNativeOn,
- isOn,
- isString,
- shouldSetAsAttr,
- } from '@vue/shared'
- import type { RendererOptions } from '@vue/runtime-core'
- import type { VueElement } from './apiCustomElement'
- type DOMRendererOptions = RendererOptions<Node, Element>
- export const patchProp: DOMRendererOptions['patchProp'] = (
- el,
- key,
- prevValue,
- nextValue,
- namespace,
- parentComponent,
- ) => {
- const isSVG = namespace === 'svg'
- if (key === 'class') {
- patchClass(el, nextValue, isSVG)
- } else if (key === 'style') {
- patchStyle(el, prevValue, nextValue)
- } else if (isOn(key)) {
- // ignore v-model listeners
- if (!isModelListener(key)) {
- patchEvent(el, key, prevValue, nextValue, parentComponent)
- }
- } else if (
- key[0] === '.'
- ? ((key = key.slice(1)), true)
- : key[0] === '^'
- ? ((key = key.slice(1)), false)
- : shouldSetAsProp(el, key, nextValue, isSVG)
- ) {
- patchDOMProp(el, key, nextValue, parentComponent)
- // #6007 also set form state as attributes so they work with
- // <input type="reset"> or libs / extensions that expect attributes
- // #11163 custom elements may use value as an prop and set it as object
- if (
- !el.tagName.includes('-') &&
- (key === 'value' || key === 'checked' || key === 'selected')
- ) {
- patchAttr(el, key, nextValue, isSVG, parentComponent, key !== 'value')
- }
- } else if (
- // #11081 force set props for possible async custom element
- (el as VueElement)._isVueCE &&
- (/[A-Z]/.test(key) || !isString(nextValue))
- ) {
- patchDOMProp(el, camelize(key), nextValue, parentComponent, key)
- } 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, parentComponent)
- }
- }
- export function shouldSetAsProp(
- el: Element,
- key: string,
- value: unknown,
- isSVG: boolean,
- ): boolean {
- if (isSVG) {
- // most keys must be set as attribute on svg elements to work
- // ...except innerHTML & textContent
- if (key === 'innerHTML' || key === 'textContent') {
- return true
- }
- // or native onclick with function values
- if (key in el && isNativeOn(key) && isFunction(value)) {
- return true
- }
- return false
- }
- if (shouldSetAsAttr(el.tagName, key)) {
- return false
- }
- // native onclick with string value, must be set as attribute
- if (isNativeOn(key) && isString(value)) {
- return false
- }
- return key in el
- }
|