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 * @deprecated
*/ */
get node() {
return this.getNode();
}
getNode() { getNode() {
return this.nodes[0]; return this.nodes[0];
} }

View File

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

View File

@ -17,7 +17,6 @@ import {
} from './upgrade-metadata'; } from './upgrade-metadata';
import { intl } from '@ali/lowcode-editor-core'; import { intl } from '@ali/lowcode-editor-core';
import { designer } from '../editor'; import { designer } from '../editor';
import { uniqueId } from '@ali/lowcode-utils';
const GlobalPropsConfigure: Array<{ const GlobalPropsConfigure: Array<{
position: string; position: string;
@ -327,24 +326,14 @@ class Prototype {
} }
setView(view: ComponentType<any>) { setView(view: ComponentType<any>) {
let wrappedView = view; this.view = 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;
const metadata = this.meta.getMetadata(); const metadata = this.meta.getMetadata();
if (!metadata.experimental) { if (!metadata.experimental) {
metadata.experimental = { metadata.experimental = {
view: wrappedView, view,
}; };
} else { } 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 { render as reactRender } from 'react-dom';
import { host } from './host'; import { host } from './host';
import SimulatorRendererView from './renderer-view'; import SimulatorRendererView from './renderer-view';
@ -7,7 +7,7 @@ import { Asset, isReactComponent } from '@ali/lowcode-utils';
import { getClientRects } from './utils/get-client-rects'; import { getClientRects } from './utils/get-client-rects';
import loader from './utils/loader'; import loader from './utils/loader';
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes'; 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'; import { RootSchema, NpmInfo, ComponentSchema, TransformStage, NodeSchema } from '@ali/lowcode-types';
// just use types // just use types
import { BuiltinSimulatorRenderer, NodeInstance, Component } from '@ali/lowcode-designer'; import { BuiltinSimulatorRenderer, NodeInstance, Component } from '@ali/lowcode-designer';
@ -443,6 +443,9 @@ function buildComponents(libraryMap: LibraryMap,
if (component && (component as ComponentSchema).componentName === 'Component') { if (component && (component as ComponentSchema).componentName === 'Component') {
components[componentName] = createComponent(component as ComponentSchema); components[componentName] = createComponent(component as ComponentSchema);
} else if (isReactComponent(component)) { } else if (isReactComponent(component)) {
if (!acceptsRef(component)) {
component = wrapReactClass(component as FunctionComponent);
}
components[componentName] = component; components[componentName] = component;
} else { } else {
component = findComponent(libraryMap, componentName, component); 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 { function getNodeInstance(fiberNode: any, specId?: string): NodeInstance<ReactInstance> | null {
const instance = fiberNode.stateNode; const instance = fiberNode?.stateNode;
if (instance && SYMBOL_VNID in instance) { if (instance && SYMBOL_VNID in instance) {
const nodeId = instance[SYMBOL_VNID]; const nodeId = instance[SYMBOL_VNID];
if (!specId || specId === nodeId) { 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 { 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> { export function isReactClass(obj: any): obj is ComponentClass<any> {
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component); 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> { export function isReactComponent(obj: any): obj is ComponentType<any> {
return obj && (isReactClass(obj) || typeof obj === 'function'); 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;
}