theme/packages/ui/src/utils/dom/create-dom-element.ts
xion 1fbf1b64d9 feat: 静态类中的函数继承范性
model onClose and ondestory函数
createDOMElemnet 从jsx
2024-09-21 17:40:53 +08:00

83 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

type JSXElement = {
type: string | symbol;
props: Record<string, any>;
key?: string | number;
};
export function createDOMElement(jsxElement: JSXElement) {
// 如果 jsxElement 是 null, undefined 或者是布尔值,则直接跳过处理
if (jsxElement == null || typeof jsxElement === 'boolean') {
console.warn('Invalid JSX element:', jsxElement);
return null;
}
const { type, props } = jsxElement;
// React Fragment 的处理
if (type === Symbol.for('react.fragment')) {
const fragment = document.createDocumentFragment();
if (props.children) {
if (Array.isArray(props.children)) {
props.children.forEach((child) => {
const childElement = createDOMElement(child);
if (childElement) {
fragment.appendChild(childElement);
}
});
} else {
const childElement = createDOMElement(props.children);
if (childElement) {
fragment.appendChild(childElement);
}
}
}
return fragment;
}
const domElement = document.createElement(type as string);
// 处理 props
Object.keys(props).forEach((prop) => {
if (prop === 'children') {
// 递归处理 children
if (Array.isArray(props.children)) {
props.children.forEach((child) => {
const childElement = createDOMElement(child);
if (childElement) {
domElement.appendChild(childElement);
}
});
} else if (typeof props.children === 'string') {
domElement.appendChild(document.createTextNode(props.children));
} else if (typeof props.children === 'object' && props.children !== null) {
const childElement = createDOMElement(props.children);
if (childElement) {
domElement.appendChild(childElement);
}
}
} else if (prop.startsWith('on')) {
// 处理事件监听器
const eventType = prop.slice(2).toLowerCase(); // 提取事件类型(如 onClick -> click
domElement.addEventListener(eventType, props[prop]);
} else if (prop === 'style' && typeof props[prop] === 'object') {
// 处理 style 属性
Object.assign(domElement.style, props[prop]);
} else if (prop === 'dangerouslySetInnerHTML') {
// 处理 dangerouslySetInnerHTML
if (props[prop] && typeof props[prop].__html === 'string') {
domElement.innerHTML = props[prop].__html;
} else {
console.warn('Invalid dangerouslySetInnerHTML content:', props[prop]);
}
} else if (prop === 'ref') {
// React 的 ref 在手动创建 DOM 时没有用处
console.warn('Ref prop is not supported in manual DOM creation');
} else if (prop === 'key') {
// React 的 key 属性是用于虚拟 DOM 的,不影响实际 DOM
console.warn('Key prop is not applicable in manual DOM creation');
} else {
// 处理其他普通属性
domElement.setAttribute(prop, props[prop]);
}
});
return domElement;
}