fix: 修复类继承 observer 过的类无法使用 super.render 的问题

This commit is contained in:
2betop 2024-10-09 19:03:58 +08:00
parent d68889430d
commit beebf72cdd
2 changed files with 72 additions and 31 deletions

View File

@ -60,6 +60,8 @@ export interface RendererBasicConfig {
isolateScope?: boolean;
isFormItem?: boolean;
autoVar?: boolean; // 自动解析变量
// 如果要替换系统渲染器,则需要设置这个为 true
override?: boolean;
// [propName:string]:any;
}
@ -107,9 +109,6 @@ export interface RendererConfig extends RendererBasicConfig {
// 异步渲染器
getComponent?: () => Promise<{default: RendererComponent} | any>;
// 如果要替换系统渲染器,则需要设置这个为 true
override?: boolean;
// 原始组件
Renderer?: RendererComponent;
}
@ -174,6 +173,29 @@ export function Renderer(config: RendererBasicConfig) {
};
}
// mobx-react 的 observer 会修改原型链的 render 方法
// 如果想继承覆盖组件的 render 方法,需要把原型链 render 还原回来
// 否则无法调用 super.render 方法
function fixMobxInjectRender<T extends Function>(klass: T): T {
const target = klass.prototype;
// mobx-react 篡改之前先记录原始 render
if (target?.render) {
target.__originRender = target.render;
}
// 将父级类上面被 mobx 篡改的 render 方法还原回来
// 而且当前类的 render 也是会被篡改的,所以父级上的其实不需要篡改
if (target?.__proto__?.hasOwnProperty('__originRender')) {
const originProto = target.__proto__;
target.__proto__ = Object.create(originProto.__proto__ || Object);
Object.assign(target.__proto__, originProto);
target.__proto__.render = originProto.__originRender;
}
return klass;
}
// 将 renderer 转成组件
function rendererToComponent(
component: RendererComponent,
@ -184,7 +206,7 @@ function rendererToComponent(
storeType: config.storeType,
extendsData: config.storeExtendsData,
shouldSyncSuperStore: config.shouldSyncSuperStore
})(observer(component));
})(observer(fixMobxInjectRender(component)));
}
if (config.isolateScope) {

View File

@ -904,48 +904,24 @@ export default class Page extends React.Component<PageProps> {
return header || right;
}
render() {
renderContent(subProps: any) {
const {
className,
store,
body,
bodyClassName,
render,
aside,
asideClassName,
classnames: cx,
showErrorMsg,
initApi,
regions,
style,
data,
asideResizor,
asideSticky,
pullRefresh,
mobileUI,
translate: __,
loadingConfig,
initApi,
id,
wrapperCustomStyle,
env,
themeCss
} = this.props;
const subProps = {
onAction: this.handleAction,
onQuery: initApi ? this.handleQuery : undefined,
onChange: this.handleChange,
onBulkChange: this.handleBulkChange,
pageLoading: store.loading
};
const hasAside = Array.isArray(regions)
? ~regions.indexOf('aside')
: aside && (!Array.isArray(aside) || aside.length);
const styleVar = buildStyle(style, data);
const pageContent = (
return (
<div className={cx('Page-content')}>
<div className={cx('Page-main')}>
{this.renderHeader()}
@ -990,6 +966,49 @@ export default class Page extends React.Component<PageProps> {
</div>
</div>
);
}
render() {
const {
className,
store,
body,
bodyClassName,
render,
aside,
asideClassName,
classnames: cx,
showErrorMsg,
initApi,
regions,
style,
data,
asideResizor,
asideSticky,
pullRefresh,
mobileUI,
translate: __,
loadingConfig,
id,
wrapperCustomStyle,
env,
themeCss
} = this.props;
const subProps = {
onAction: this.handleAction,
onQuery: initApi ? this.handleQuery : undefined,
onChange: this.handleChange,
onBulkChange: this.handleBulkChange,
pageLoading: store.loading
};
const hasAside = Array.isArray(regions)
? ~regions.indexOf('aside')
: aside && (!Array.isArray(aside) || aside.length);
const styleVar = buildStyle(style, data);
const pageContent = this.renderContent(subProps);
return (
<div