feat: 静态类中的函数继承范性
model onClose and ondestory函数 createDOMElemnet 从jsx
This commit is contained in:
@@ -14,7 +14,7 @@ export const App = () => {
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path='/' element={<Navigate to='/model/' />} />
|
||||
<Route path='/model/*' element={<FlowApps />} />
|
||||
<Route path='/modal/*' element={<FlowApps />} />
|
||||
<Route path='/codemirror/*' element={<CodeMirrorApp />} />
|
||||
<Route path='/404' element={<div>404</div>} />
|
||||
<Route path='*' element={<div>404</div>} />
|
||||
|
||||
79
packages/theme-preview/src/pages/model/create-dom.ts
Normal file
79
packages/theme-preview/src/pages/model/create-dom.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
export function createDOMElement(jsxElement: JSX.Element) {
|
||||
// 如果 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);
|
||||
|
||||
// 处理 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;
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { modalStore, Modal, DialogModal } from '@kevisual/ui';
|
||||
import { calc } from 'antd/es/theme/internal';
|
||||
import { DialogModal, Modal, modalStore } from '@kevisual/ui';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import '@kevisual/ui/src/index.css';
|
||||
import { createDOMElement } from './create-dom';
|
||||
// import '@kevisual/ui/src/components/modal/index.css';
|
||||
export const App = () => {
|
||||
const showModel = () => {
|
||||
//
|
||||
@@ -17,6 +19,8 @@ export const App = () => {
|
||||
}}>
|
||||
<ModelOne />
|
||||
<ModelTwo />
|
||||
<ModelTwo2 />
|
||||
<ModelThree />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -29,7 +33,7 @@ const ModelOne = () => {
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className='w-100 h-100 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
<div className='w-96 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
model one
|
||||
<div className='cursor-pointer p-2 border' onClick={showModel}>
|
||||
show
|
||||
@@ -50,12 +54,12 @@ const ModelTwo = () => {
|
||||
contentStyle: {
|
||||
// maxHeight: '100px',
|
||||
// overflow: 'auto',
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className='w-100 h-100 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
<div className='w-96 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
model two
|
||||
<div className='cursor-pointer p-2 border' onClick={showModel}>
|
||||
show
|
||||
@@ -71,3 +75,130 @@ const ModelTwo = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const ModelTwo2 = () => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const showModel = () => {
|
||||
const div = createDOMElement(refHide);
|
||||
const model = DialogModal.render(ref.current! || div, {
|
||||
dialogTitle: 'Dialog Modal',
|
||||
width: '400px',
|
||||
dialogTitleCloseIcon: true,
|
||||
contentStyle: {
|
||||
// maxHeight: '100px',
|
||||
// overflow: 'auto',
|
||||
},
|
||||
});
|
||||
};
|
||||
const refHide = (
|
||||
<div ref={ref}>
|
||||
当前元素是Modal Dialog 的渲染内容
|
||||
<div>内容</div>
|
||||
<div>内容2</div>
|
||||
<div>内容3</div>
|
||||
<div>内容4</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<div className='w-96 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
model two -假入ref的模块没有真实渲染到节点,如何处理。createDOMElement
|
||||
<div className='cursor-pointer p-2 border' onClick={showModel}>
|
||||
show
|
||||
</div>
|
||||
<div className='hidden'>{refHide}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ModelThree = () => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
let dialog = useRef<DialogModal | null>(null);
|
||||
const showModel = () => {
|
||||
const model = DialogModal.render(ref.current!, {
|
||||
dialogTitle: 'Dialog Modal',
|
||||
width: '400px',
|
||||
dialogTitleCloseIcon: true,
|
||||
open: false,
|
||||
contentStyle: {
|
||||
// maxHeight: '100px',
|
||||
// overflow: 'auto',
|
||||
},
|
||||
});
|
||||
const modals = modalStore.getState().modals;
|
||||
console.log('modals', modals.length, model);
|
||||
dialog.current = model;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className='w-96 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
model 3
|
||||
<div className='cursor-pointer p-2 border' onClick={showModel}>
|
||||
show
|
||||
</div>
|
||||
<div ref={ref}>
|
||||
当前元素是Modal Dialog 的渲染内容
|
||||
<div>内容</div>
|
||||
<div>内容2</div>
|
||||
<div>内容3</div>
|
||||
<div>内容4</div>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
if (dialog.current) {
|
||||
dialog.current.setOpen(true);
|
||||
}
|
||||
console.log('open', dialog.current);
|
||||
}}>
|
||||
真打开
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Model4 = () => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
let dialog = useRef<DialogModal | null>(null);
|
||||
const showModel = () => {
|
||||
const model = DialogModal.create({
|
||||
dialogTitle: 'Dialog Modal',
|
||||
width: '400px',
|
||||
dialogTitleCloseIcon: true,
|
||||
open: false,
|
||||
contentStyle: {
|
||||
// maxHeight: '100px',
|
||||
// overflow: 'auto',
|
||||
},
|
||||
});
|
||||
const modals = modalStore.getState().modals;
|
||||
console.log('modals', modals.length, model);
|
||||
dialog.current = model;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className='w-96 p-4 rounded-md shadow-md bg-slate-200'>
|
||||
model 4
|
||||
<div className='cursor-pointer p-2 border' onClick={showModel}>
|
||||
show
|
||||
</div>
|
||||
<div ref={ref}>
|
||||
当前元素是Modal Dialog 的渲染内容
|
||||
<div>内容</div>
|
||||
<div>内容2</div>
|
||||
<div>内容3</div>
|
||||
<div>内容4</div>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
if (dialog.current) {
|
||||
dialog.current.setOpen(true);
|
||||
}
|
||||
console.log('open', dialog.current);
|
||||
}}>
|
||||
真打开
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
20
packages/theme-preview/src/pages/model/type.ts
Normal file
20
packages/theme-preview/src/pages/model/type.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
class A {
|
||||
constructor() {}
|
||||
|
||||
// 使用泛型和类构造函数签名来推断返回的类型
|
||||
static render<T extends new (...args: any[]) => any>(this: T, el: string | HTMLDivElement): InstanceType<T> {
|
||||
return new this();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
const a = A.render('div');
|
||||
const b = B.render('div');
|
||||
|
||||
// type a == A
|
||||
// type b == B
|
||||
Reference in New Issue
Block a user