2024-03-19 00:24:58 +08:00
|
|
|
import { camelize, isArray, isFunction } from '@vue/shared'
|
|
|
|
import { type ComponentInternalInstance, currentInstance } from './component'
|
2024-03-16 18:54:36 +08:00
|
|
|
import { isEmitListener } from './componentEmits'
|
2024-03-19 00:24:58 +08:00
|
|
|
import { setDynamicProps } from './dom/prop'
|
|
|
|
import type { RawProps } from './componentProps'
|
|
|
|
import { renderEffect } from './renderEffect'
|
2024-03-16 18:54:36 +08:00
|
|
|
|
|
|
|
export function patchAttrs(instance: ComponentInternalInstance) {
|
2024-04-15 02:58:32 +08:00
|
|
|
const {
|
|
|
|
attrs,
|
|
|
|
rawProps,
|
|
|
|
propsOptions: [options],
|
|
|
|
} = instance
|
2024-03-16 18:54:36 +08:00
|
|
|
|
2024-04-30 23:09:59 +08:00
|
|
|
if (!rawProps.length) return
|
2024-03-16 18:54:36 +08:00
|
|
|
const keys = new Set<string>()
|
2024-04-30 23:09:59 +08:00
|
|
|
for (const props of Array.from(rawProps).reverse()) {
|
|
|
|
if (isFunction(props)) {
|
|
|
|
const resolved = props()
|
|
|
|
for (const rawKey in resolved) {
|
|
|
|
registerAttr(rawKey, resolved[rawKey])
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (const rawKey in props) {
|
|
|
|
registerAttr(rawKey, props[rawKey], true)
|
2024-03-16 18:54:36 +08:00
|
|
|
}
|
|
|
|
}
|
2024-04-30 23:09:59 +08:00
|
|
|
}
|
2024-03-16 18:54:36 +08:00
|
|
|
|
|
|
|
for (const key in attrs) {
|
|
|
|
if (!keys.has(key)) {
|
|
|
|
delete attrs[key]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-30 23:09:59 +08:00
|
|
|
function registerAttr(key: string, value: any, getter?: boolean) {
|
2024-03-16 18:54:36 +08:00
|
|
|
if (
|
|
|
|
(!options || !(camelize(key) in options)) &&
|
2024-04-30 23:09:59 +08:00
|
|
|
!isEmitListener(instance.emitsOptions, key) &&
|
|
|
|
!keys.has(key)
|
2024-03-16 18:54:36 +08:00
|
|
|
) {
|
|
|
|
keys.add(key)
|
2024-04-30 23:09:59 +08:00
|
|
|
if (getter) {
|
|
|
|
Object.defineProperty(attrs, key, {
|
|
|
|
get: value,
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
attrs[key] = value
|
|
|
|
}
|
2024-03-16 18:54:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 00:24:58 +08:00
|
|
|
|
|
|
|
export function withAttrs(props: RawProps): RawProps {
|
|
|
|
const instance = currentInstance!
|
2024-06-21 14:03:11 +08:00
|
|
|
if (instance.type.inheritAttrs === false) return props
|
2024-03-19 00:24:58 +08:00
|
|
|
const attrsGetter = () => instance.attrs
|
|
|
|
if (!props) return [attrsGetter]
|
|
|
|
if (isArray(props)) {
|
|
|
|
return [attrsGetter, ...props]
|
|
|
|
}
|
|
|
|
return [attrsGetter, props]
|
|
|
|
}
|
|
|
|
|
|
|
|
export function fallThroughAttrs(instance: ComponentInternalInstance) {
|
|
|
|
const {
|
|
|
|
block,
|
2024-06-21 14:03:11 +08:00
|
|
|
type: { inheritAttrs },
|
2024-03-19 00:24:58 +08:00
|
|
|
} = instance
|
|
|
|
if (inheritAttrs === false) return
|
|
|
|
|
|
|
|
if (block instanceof Element) {
|
|
|
|
renderEffect(() => setDynamicProps(block, instance.attrs))
|
|
|
|
}
|
|
|
|
}
|