fix: 在 renderer 层面做 function component 包装,避免影响 rax 等其他场景

This commit is contained in:
力皓 2020-08-26 21:22:56 +08:00
parent 4369499458
commit 1f920dd959
5 changed files with 33 additions and 19 deletions

View File

@ -228,6 +228,9 @@ export class SettingTopEntry implements SettingEntry {
/**
* @deprecated
*/
get node() {
return this.getNode();
}
getNode() {
return this.nodes[0];
}

View File

@ -2,6 +2,7 @@ import lg from '@ali/vu-logger';
import { ComponentClass, ComponentType } from 'react';
import Prototype, { isPrototype } from './prototype';
import { designer } from '../editor';
import { upgradeMetadata } from './upgrade-metadata';
import trunk from './trunk';
function basename(name: string) {
@ -125,6 +126,8 @@ export default class Bundle {
*/
if (bundles.length >= 2) {
const prototype = bundles[0];
// const metadata = upgradeMetadata(prototype.options);
// prototype.meta = designer.createComponentMeta(metadata);
const prototypeView = bundles[1];
prototype.setView(prototypeView);
this.registerPrototype(prototype);

View File

@ -17,7 +17,6 @@ import {
} from './upgrade-metadata';
import { intl } from '@ali/lowcode-editor-core';
import { designer } from '../editor';
import { uniqueId } from '@ali/lowcode-utils';
const GlobalPropsConfigure: Array<{
position: string;
@ -327,24 +326,14 @@ class Prototype {
}
setView(view: ComponentType<any>) {
let wrappedView = view;
if (!view?.prototype?.isReactComponent) {
const ViewComponentClass = class extends Component {
render() {
return (view as FunctionComponent)(this.props);
}
} as any;
ViewComponentClass.displayName = view.displayName;
wrappedView = ViewComponentClass;
}
this.view = wrappedView;
this.view = view;
const metadata = this.meta.getMetadata();
if (!metadata.experimental) {
metadata.experimental = {
view: wrappedView,
view,
};
} else {
metadata.experimental.view = wrappedView;
metadata.experimental.view = view;
}
}

View File

@ -1,4 +1,4 @@
import React, { createElement, ReactInstance, ComponentType, ReactElement } from 'react';
import React, { createElement, ReactInstance, ComponentType, ReactElement, FunctionComponent } from 'react';
import { render as reactRender } from 'react-dom';
import { host } from './host';
import SimulatorRendererView from './renderer-view';
@ -7,7 +7,7 @@ import { Asset, isReactComponent } from '@ali/lowcode-utils';
import { getClientRects } from './utils/get-client-rects';
import loader from './utils/loader';
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
import { isESModule, isElement, acceptsRef, wrapReactClass, cursor, setNativeSelection } from '@ali/lowcode-utils';
import { RootSchema, NpmInfo, ComponentSchema, TransformStage, NodeSchema } from '@ali/lowcode-types';
// just use types
import { BuiltinSimulatorRenderer, NodeInstance, Component } from '@ali/lowcode-designer';
@ -443,6 +443,9 @@ function buildComponents(libraryMap: LibraryMap,
if (component && (component as ComponentSchema).componentName === 'Component') {
components[componentName] = createComponent(component as ComponentSchema);
} else if (isReactComponent(component)) {
if (!acceptsRef(component)) {
component = wrapReactClass(component as FunctionComponent);
}
components[componentName] = component;
} else {
component = findComponent(libraryMap, componentName, component);
@ -497,7 +500,7 @@ function getClosestNodeInstance(from: ReactInstance, specId?: string): NodeInsta
}
function getNodeInstance(fiberNode: any, specId?: string): NodeInstance<ReactInstance> | null {
const instance = fiberNode.stateNode;
const instance = fiberNode?.stateNode;
if (instance && SYMBOL_VNID in instance) {
const nodeId = instance[SYMBOL_VNID];
if (!specId || specId === nodeId) {
@ -507,7 +510,7 @@ function getNodeInstance(fiberNode: any, specId?: string): NodeInstance<ReactIns
};
}
}
return getNodeInstance(fiberNode.return);
return getNodeInstance(fiberNode?.return);
}
function checkInstanceMounted(instance: any): boolean {

View File

@ -1,9 +1,25 @@
import { ComponentClass, Component, ComponentType } from 'react';
import { ComponentClass, Component, FunctionComponent, ComponentType } from 'react';
const hasSymbol = typeof Symbol === 'function' && Symbol['for'];
const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol['for']('react.forward_ref') : 0xead0;
export function isReactClass(obj: any): obj is ComponentClass<any> {
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component);
}
export function acceptsRef(obj: any): boolean {
return obj?.prototype?.isReactComponent || (obj.$$typeof && obj.$$typeof === REACT_FORWARD_REF_TYPE);
}
export function isReactComponent(obj: any): obj is ComponentType<any> {
return obj && (isReactClass(obj) || typeof obj === 'function');
}
export function wrapReactClass(view: FunctionComponent) {
const ViewComponentClass = class extends Component {
render() {
return view(this.props);
}
} as any;
ViewComponentClass.displayName = view.displayName;
return ViewComponentClass;
}