refactor: replace engine to renderer, remove iceluna

This commit is contained in:
wuji.xwt 2020-07-16 21:05:00 +08:00
parent 199ed2b9cd
commit d5140c91a0
19 changed files with 303 additions and 243 deletions

View File

@ -0,0 +1,8 @@
import React, { PureComponent } from 'react';
export default class AView extends PureComponent {
static displayName = 'A';
static version = '0.0.0';
render() {
return <a {...this.props} />;
}
}

View File

@ -0,0 +1,8 @@
import React, { PureComponent } from 'react';
export default class DivView extends PureComponent {
static displayName = 'Div';
static version = '0.0.0';
render() {
return <div {...this.props} />;
}
}

View File

@ -0,0 +1,11 @@
import React, { PureComponent } from 'react';
export default class ImageView extends PureComponent {
static displayName = 'Image';
static version = '0.0.0';
static defaultProps = {
src: '//img.alicdn.com/tfs/TB1knm4bqNj0u4jSZFyXXXgMVXa-240-240.png_100x100.jpg',
};
render() {
return <img {...this.props} />;
}
}

View File

@ -0,0 +1,23 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
export default class TextView extends PureComponent {
static displayName = 'Text';
static version = '0.0.0';
static propTypes = {
text: PropTypes.string,
};
render() {
const { text, ...restProps } = this.props;
let textNode = text;
//
try {
textNode = text.toString();
} catch (e) {
textNode = '';
}
if (window.__ctx && window.__ctx.canvasAppHelper) {
textNode = textNode || 'Text';
}
return <span {...restProps}>{textNode}</span>;
}
}

View File

@ -1,7 +1,7 @@
import Div from '@ali/iceluna-components-div';
import Text from '@ali/iceluna-components-text';
import A from '@ali/iceluna-components-a';
import Image from '@ali/iceluna-components-image';
import Div from './Div';
import Text from './Text';
import A from './A';
import Image from './Image';
import {
Balloon,

View File

@ -8,7 +8,7 @@ import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import ReactRenderer from '@ali/lowcode-react-renderer';
import schema from './schemas/list';
import components from './config/components';
import components from './config/components/index';
import utils from './config/utils';
import constants from './config/constants';

View File

@ -8,7 +8,7 @@ import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import ReactRenderer from '@ali/lowcode-react-renderer';
import schema from './schemas/table';
import components from './config/components';
import components from './config/components/index';
import utils from './config/utils';
import constants from './config/constants';

View File

@ -26,7 +26,6 @@
"dependencies": {
"@ali/b3-one": "^0.0.17",
"@ali/bzb-request": "^2.6.0-beta.13",
"@ali/iceluna-comp-div": "^1.0.0",
"@ali/lib-mtop": "^2.5.1",
"@alifd/next": "^1.18.17",
"debug": "^4.1.1",
@ -43,10 +42,6 @@
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@ali/iceluna-components-a": "^0.1.0",
"@ali/iceluna-components-div": "^0.1.0",
"@ali/iceluna-components-image": "^0.1.0",
"@ali/iceluna-components-text": "^0.1.0",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.10",
"build-plugin-fusion": "^0.1.0",

View File

@ -0,0 +1,11 @@
import React, { PureComponent } from 'react';
export default class DivView extends PureComponent {
static displayName = 'Div';
static version = '0.0.0';
render() {
return <div {...this.props} />;
}
}

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import './index.scss';
import './VisualDom.scss';
export default class VisualDom extends PureComponent {
static displayName = 'VisualDom';
static propTypes = {

View File

@ -1,199 +0,0 @@
import React, { Component, PureComponent, createElement as reactCreateElement } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Debug from 'debug';
import AppContext from '../context/appContext';
import { isFileSchema, goldlog } from '../utils';
import PageEngine from './pageEngine';
import ComponentEngine from './compEngine';
import BlockEngine from './blockEngine';
import AddonEngine from './addonEngine';
import TempEngine from './tempEngine';
import { isEmpty } from '@ali/b3-one/lib/obj';
import BaseEngine from './base';
import Div from '@ali/iceluna-comp-div';
window.React = React;
window.ReactDom = ReactDOM;
const debug = Debug('engine:entry');
const ENGINE_COMPS = {
PageEngine,
ComponentEngine,
BlockEngine,
AddonEngine,
TempEngine,
DivEngine: BlockEngine,
};
class FaultComponent extends PureComponent {
render() {
// FIXME: errorlog
console.error('render error', this.props);
return <Div>RenderError</Div>;
}
}
class NotFoundComponent extends PureComponent {
render() {
console.error('component not found', this.props);
return <Div {...this.props} />;
}
}
function isReactClass(obj) {
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component);
}
export default class Engine extends PureComponent {
static dislayName = 'engine';
static propTypes = {
appHelper: PropTypes.object,
components: PropTypes.object,
designMode: PropTypes.string,
suspended: PropTypes.bool,
schema: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
onCompGetRef: PropTypes.func,
onCompGetCtx: PropTypes.func,
customCreateElement: PropTypes.func,
};
static defaultProps = {
appHelper: null,
components: {},
designMode: '',
suspended: false,
schema: {},
onCompGetRef: () => {},
onCompGetCtx: () => {},
};
constructor(props, context) {
super(props, context);
this.state = {};
debug(`entry.constructor - ${props.schema && props.schema.componentName}`);
}
async componentDidMount() {
goldlog(
'EXP',
{
action: 'appear',
value: !!this.props.designMode,
},
'engine',
);
debug(`entry.componentDidMount - ${this.props.schema && this.props.schema.componentName}`);
}
async componentDidUpdate() {
debug(`entry.componentDidUpdate - ${this.props.schema && this.props.schema.componentName}`);
}
async componentWillUnmount() {
debug(`entry.componentWillUnmount - ${this.props.schema && this.props.schema.componentName}`);
}
async componentDidCatch(e) {
console.warn(e);
}
shouldComponentUpdate(nextProps) {
return !nextProps.suspended;
}
__getRef = (ref) => {
this.__ref = ref;
if (ref) {
this.props.onCompGetRef(this.props.schema, ref, true);
}
};
patchDidCatch(Component) {
if (!isReactClass(Component)) {
return;
}
if (Component.patchedCatch) {
return;
}
Component.patchedCatch = true;
Component.getDerivedStateFromError = (error) => {
return { engineRenderError: true, error };
};
const engine = this;
const originRender = Component.prototype.render;
Component.prototype.render = function () {
if (this.state && this.state.engineRenderError) {
this.state.engineRenderError = false;
return engine.createElement(engine.getFaultComponent(), {
...this.props,
error: this.state.error,
});
}
return originRender.call(this);
};
const originShouldComponentUpdate = Component.prototype.shouldComponentUpdate;
Component.prototype.shouldComponentUpdate = function (nextProps, nextState) {
if (nextState && nextState.engineRenderError) {
return true;
}
return originShouldComponentUpdate ? originShouldComponentUpdate.call(this, nextProps, nextState) : true;
};
}
createElement(Component, props, children) {
// TODO: enable in runtime mode?
this.patchDidCatch(Component);
return (this.props.customCreateElement || reactCreateElement)(Component, props, children);
}
getNotFoundComponent() {
return this.props.notFoundComponent || NotFoundComponent;
}
getFaultComponent() {
return this.props.faultComponent || FaultComponent;
}
render() {
const { schema, designMode, appHelper, components, customCreateElement } = this.props;
if (isEmpty(schema)) {
return null;
}
//
if (schema.componentName !== 'Div' && !isFileSchema(schema)) {
return '模型结构异常';
}
debug('entry.render');
const { componentName } = schema;
const allComponents = { ...ENGINE_COMPS, ...components };
let Comp = allComponents[componentName] || ENGINE_COMPS[`${componentName}Engine`];
if (Comp && Comp.prototype) {
const proto = Comp.prototype;
if (!(Comp.prototype instanceof BaseEngine)) {
Comp = ENGINE_COMPS[`${componentName}Engine`];
}
}
if (Comp) {
return (
<AppContext.Provider
value={{
appHelper,
components: allComponents,
engine: this,
}}
>
<Comp
key={schema.__ctx && `${schema.__ctx.lunaKey}_${schema.__ctx.idx || '0'}`}
ref={this.__getRef}
__appHelper={appHelper}
__components={allComponents}
__schema={schema}
__designMode={designMode}
{...this.props}
/>
</AppContext.Provider>
);
}
return null;
}
}
Engine.findDOMNode = ReactDOM.findDOMNode;

View File

@ -1 +1,199 @@
export default from './engine';
import React, { Component, PureComponent, createElement as reactCreateElement } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Debug from 'debug';
import { isEmpty } from '@ali/b3-one/lib/obj';
import AppContext from './context/appContext';
import { isFileSchema, goldlog } from './utils';
import PageEngine from './renderer/page';
import ComponentEngine from './renderer/component';
import BlockEngine from './renderer/block';
import AddonEngine from './renderer/addon';
import TempEngine from './renderer/temp';
import BaseEngine from './renderer/base';
import Div from './components/Div';
window.React = React;
window.ReactDom = ReactDOM;
const debug = Debug('renderer:entry');
const ENGINE_COMPS = {
PageEngine,
ComponentEngine,
BlockEngine,
AddonEngine,
TempEngine,
DivEngine: BlockEngine,
};
class FaultComponent extends PureComponent {
render() {
// FIXME: errorlog
console.error('render error', this.props);
return <Div>RenderError</Div>;
}
}
class NotFoundComponent extends PureComponent {
render() {
console.error('component not found', this.props);
return <Div {...this.props} />;
}
}
function isReactClass(obj) {
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component);
}
export default class Renderer extends PureComponent {
static dislayName = 'renderer';
static propTypes = {
appHelper: PropTypes.object,
components: PropTypes.object,
designMode: PropTypes.string,
suspended: PropTypes.bool,
schema: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
onCompGetRef: PropTypes.func,
onCompGetCtx: PropTypes.func,
customCreateElement: PropTypes.func,
};
static defaultProps = {
appHelper: null,
components: {},
designMode: '',
suspended: false,
schema: {},
onCompGetRef: () => {},
onCompGetCtx: () => {},
};
constructor(props, context) {
super(props, context);
this.state = {};
debug(`entry.constructor - ${props.schema && props.schema.componentName}`);
}
async componentDidMount() {
goldlog(
'EXP',
{
action: 'appear',
value: !!this.props.designMode,
},
'engine',
);
debug(`entry.componentDidMount - ${this.props.schema && this.props.schema.componentName}`);
}
async componentDidUpdate() {
debug(`entry.componentDidUpdate - ${this.props.schema && this.props.schema.componentName}`);
}
async componentWillUnmount() {
debug(`entry.componentWillUnmount - ${this.props.schema && this.props.schema.componentName}`);
}
async componentDidCatch(e) {
console.warn(e);
}
shouldComponentUpdate(nextProps) {
return !nextProps.suspended;
}
__getRef = (ref) => {
this.__ref = ref;
if (ref) {
this.props.onCompGetRef(this.props.schema, ref, true);
}
};
patchDidCatch(Component) {
if (!isReactClass(Component)) {
return;
}
if (Component.patchedCatch) {
return;
}
Component.patchedCatch = true;
Component.getDerivedStateFromError = (error) => {
return { engineRenderError: true, error };
};
const engine = this;
const originRender = Component.prototype.render;
Component.prototype.render = function () {
if (this.state && this.state.engineRenderError) {
this.state.engineRenderError = false;
return engine.createElement(engine.getFaultComponent(), {
...this.props,
error: this.state.error,
});
}
return originRender.call(this);
};
const originShouldComponentUpdate = Component.prototype.shouldComponentUpdate;
Component.prototype.shouldComponentUpdate = function (nextProps, nextState) {
if (nextState && nextState.engineRenderError) {
return true;
}
return originShouldComponentUpdate ? originShouldComponentUpdate.call(this, nextProps, nextState) : true;
};
}
createElement(Component, props, children) {
// TODO: enable in runtime mode?
this.patchDidCatch(Component);
return (this.props.customCreateElement || reactCreateElement)(Component, props, children);
}
getNotFoundComponent() {
return this.props.notFoundComponent || NotFoundComponent;
}
getFaultComponent() {
return this.props.faultComponent || FaultComponent;
}
render() {
const { schema, designMode, appHelper, components, customCreateElement } = this.props;
if (isEmpty(schema)) {
return null;
}
// 兼容乐高区块模板
if (schema.componentName !== 'Div' && !isFileSchema(schema)) {
return '模型结构异常';
}
debug('entry.render');
const { componentName } = schema;
const allComponents = { ...ENGINE_COMPS, ...components };
let Comp = allComponents[componentName] || ENGINE_COMPS[`${componentName}Engine`];
if (Comp && Comp.prototype) {
const proto = Comp.prototype;
if (!(Comp.prototype instanceof BaseEngine)) {
Comp = ENGINE_COMPS[`${componentName}Engine`];
}
}
if (Comp) {
return (
<AppContext.Provider
value={{
appHelper,
components: allComponents,
engine: this,
}}
>
<Comp
key={schema.__ctx && `${schema.__ctx.lunaKey}_${schema.__ctx.idx || '0'}`}
ref={this.__getRef}
__appHelper={appHelper}
__components={allComponents}
__schema={schema}
__designMode={designMode}
{...this.props}
/>
</AppContext.Provider>
);
}
return null;
}
}
Renderer.findDOMNode = ReactDOM.findDOMNode;

View File

@ -1,13 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';
import Debug from 'debug';
import AppContext from '../context/appContext';
import classnames from 'classnames';
import BaseEngine from './base';
import AppContext from '../context/appContext';
import BaseRenderer from './base';
import { isSchema, getFileCssName, isEmpty, goldlog } from '../utils';
const debug = Debug('engine:addon');
export default class AddonEngine extends BaseEngine {
static dislayName = 'addon-engine';
const debug = Debug('renderer:addon');
export default class AddonRenderer extends BaseRenderer {
static dislayName = 'addon-renderer';
static propTypes = {
config: PropTypes.object,
__schema: PropTypes.object,

View File

@ -1,12 +1,10 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Debug from 'debug';
import Div from '@ali/iceluna-comp-div';
import VisualDom from '../comp/visualDom';
import Div from '../components/Div';
import VisualDom from '../components/VisualDom';
import AppContext from '../context/appContext';
import DataHelper from '../utils/dataHelper';
import {
forEach,
getValue,
@ -25,7 +23,7 @@ import {
acceptsRef,
} from '../utils';
const debug = Debug('engine:base');
const debug = Debug('renderer:base');
const DESIGN_MODE = {
EXTEND: 'extend',
BORDER: 'border',
@ -34,8 +32,8 @@ const DESIGN_MODE = {
const OVERLAY_LIST = ['Dialog', 'Overlay', 'Animate', 'ConfigProvider'];
let scopeIdx = 0;
export default class BaseEngine extends PureComponent {
static dislayName = 'base-engine';
export default class BaseRender extends PureComponent {
static dislayName = 'base-renderer';
static propTypes = {
locale: PropTypes.string,
messages: PropTypes.object,

View File

@ -4,13 +4,14 @@ import Debug from 'debug';
import classnames from 'classnames';
import Loading from '@alifd/next/lib/loading';
import '@alifd/next/lib/loading/style';
import BaseEngine from './base';
import BaseRenderer from './base';
import AppContext from '../context/appContext';
import { isSchema, getFileCssName } from '../utils';
const debug = Debug('engine:block');
export default class BlockEngine extends BaseEngine {
static dislayName = 'block-engine';
const debug = Debug('renderer:block');
export default class BlockRenderer extends BaseRenderer {
static dislayName = 'block-renderer';
static propTypes = {
__schema: PropTypes.object,
};

View File

@ -4,13 +4,14 @@ import Debug from 'debug';
import classnames from 'classnames';
import Loading from '@alifd/next/lib/loading';
import '@alifd/next/lib/loading/style';
import AppContext from '../context/appContext';
import BaseEngine from './base';
import BaseRenderer from './base';
import { isSchema, getFileCssName } from '../utils';
const debug = Debug('engine:comp');
export default class CompEngine extends BaseEngine {
static dislayName = 'comp-engine';
const debug = Debug('renderer:comp');
export default class CompRenderer extends BaseRenderer {
static dislayName = 'comp-renderer';
static propTypes = {
__schema: PropTypes.object,
};

View File

@ -5,12 +5,13 @@ import classnames from 'classnames';
import Loading from '@alifd/next/lib/loading';
import '@alifd/next/lib/loading/style';
import AppContext from '../context/appContext';
import BaseEngine from './base';
import BaseRenderer from './base';
import { isSchema, getFileCssName } from '../utils';
const debug = Debug('engine:page');
export default class PageEngine extends BaseEngine {
static dislayName = 'page-engine';
const debug = Debug('renderer:page');
export default class PageRenderer extends BaseRenderer {
static dislayName = 'page-renderer';
static propTypes = {
__schema: PropTypes.object,
};

View File

@ -2,11 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import Debug from 'debug';
import AppContext from '../context/appContext';
import BaseEngine from './base';
import BaseRenderer from './base';
import { isSchema } from '../utils';
const debug = Debug('engine:temp');
export default class TempEngine extends BaseEngine {
static dislayName = 'temp-engine';
const debug = Debug('renderer:temp');
export default class TempRenderer extends BaseRenderer {
static dislayName = 'temp-renderer';
static propTypes = {
__ctx: PropTypes.object,
__schema: PropTypes.object,
@ -52,7 +54,7 @@ export default class TempEngine extends BaseEngine {
render() {
const { __schema, __ctx } = this.props;
if (!isSchema(__schema, true) || __schema.componentName !== 'Temp') {
return '下钻编辑schema结构异常';
return '下钻编辑 schema 结构异常!';
}
debug(`temp.render - ${__schema.fileName}`);