mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-02-28 04:40:32 +00:00
feat: ReactProvider
This commit is contained in:
parent
75a2020a6e
commit
0e50a2056a
4
packages/react-provider/CHANGELOG.md
Normal file
4
packages/react-provider/CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
1
packages/react-provider/README.md
Normal file
1
packages/react-provider/README.md
Normal file
@ -0,0 +1 @@
|
||||
# 低代码引擎运行时框架
|
||||
5
packages/react-provider/build.json
Normal file
5
packages/react-provider/build.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": [
|
||||
"build-plugin-component"
|
||||
]
|
||||
}
|
||||
43
packages/react-provider/package.json
Normal file
43
packages/react-provider/package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@ali/lowcode-react-provider",
|
||||
"version": "0.8.14",
|
||||
"description": "React Provider for Runtime",
|
||||
"files": [
|
||||
"es",
|
||||
"lib"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
"scripts": {
|
||||
"build": "build-scripts build --skip-demo",
|
||||
"test": "ava",
|
||||
"test:snapshot": "ava --update-snapshots"
|
||||
},
|
||||
"ava": {
|
||||
"compileEnhancements": false,
|
||||
"snapshotDir": "test/fixtures/__snapshots__",
|
||||
"extensions": [
|
||||
"ts"
|
||||
],
|
||||
"require": [
|
||||
"ts-node/register"
|
||||
]
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ali/lowcode-runtime": "^0.8.13",
|
||||
"react": "^16",
|
||||
"react-dom": "^16",
|
||||
"@recore/router": "^1.0.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"build-plugin-component": "^0.2.16",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/react": "^16",
|
||||
"@types/react-dom": "^16"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npm.alibaba-inc.com"
|
||||
}
|
||||
}
|
||||
5
packages/react-provider/src/index.ts
Normal file
5
packages/react-provider/src/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import ReactProvider from './provider';
|
||||
import { Router } from '@recore/router';
|
||||
|
||||
export { Router };
|
||||
export default ReactProvider;
|
||||
43
packages/react-provider/src/lazy-component.tsx
Normal file
43
packages/react-provider/src/lazy-component.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { Component, createElement } from 'react';
|
||||
import { app } from '@ali/lowcode-runtime';
|
||||
|
||||
interface IProps {
|
||||
getPageData: () => any;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
schema: object | null;
|
||||
}
|
||||
|
||||
export default class LazyComponent extends Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
schema: null,
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const { getPageData } = this.props;
|
||||
if (getPageData && !this.state.schema) {
|
||||
const schema = await getPageData();
|
||||
this.setState({ schema });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getPageData, ...restProps } = this.props;
|
||||
const { schema } = this.state;
|
||||
const Renderer = app.getRenderer();
|
||||
const Loading = app.getLoading();
|
||||
if (!Renderer || !schema) {
|
||||
if (!Loading) {
|
||||
return null;
|
||||
}
|
||||
// loading扩展点
|
||||
return createElement(Loading);
|
||||
}
|
||||
return createElement(Renderer as any, { schema, loading: Loading ? createElement(Loading) : null, ...restProps });
|
||||
}
|
||||
}
|
||||
104
packages/react-provider/src/provider.tsx
Normal file
104
packages/react-provider/src/provider.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
import { createElement, ReactType, ReactElement } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router } from '@recore/router';
|
||||
import { app, Provider } from '@ali/lowcode-runtime';
|
||||
import LazyComponent from './lazy-component';
|
||||
|
||||
export default class ReactProvider extends Provider {
|
||||
// 定制构造根组件的逻辑,如切换路由机制
|
||||
createApp() {
|
||||
const RouterView = this.getRouterView();
|
||||
let App;
|
||||
const layoutConfig = this.getLayoutConfig();
|
||||
if (!layoutConfig || !layoutConfig.componentName) {
|
||||
App = (props: any) => (RouterView ? createElement(RouterView, { ...props }) : null);
|
||||
return App;
|
||||
}
|
||||
const { componentName: layoutName, props: layoutProps } = layoutConfig;
|
||||
const { content: Layout, props: extraLayoutProps } = app.getLayout(layoutName) || {};
|
||||
const sectionalRender = this.isSectionalRender();
|
||||
if (!sectionalRender && Layout) {
|
||||
App = (props: any) =>
|
||||
createElement(
|
||||
Layout,
|
||||
{ ...layoutProps, ...extraLayoutProps },
|
||||
RouterView ? createElement(RouterView, props) : null,
|
||||
);
|
||||
} else {
|
||||
App = (props: any) => (RouterView ? createElement(RouterView, props) : null);
|
||||
}
|
||||
return App;
|
||||
}
|
||||
|
||||
runApp(App: any, config: any) {
|
||||
ReactDOM.render(<App />, document.getElementById(config?.containerId || 'App'));
|
||||
}
|
||||
|
||||
// 内置实现 for 动态化渲染
|
||||
getRouterView(): ReactType | null {
|
||||
const routerConfig = this.getRouterConfig();
|
||||
if (!routerConfig) {
|
||||
return null;
|
||||
}
|
||||
const routes: Array<{
|
||||
path: string;
|
||||
children: any;
|
||||
exact: boolean;
|
||||
defined: { keepAlive: boolean; [key: string]: any };
|
||||
}> = [];
|
||||
let homePageId = this.getHomePage();
|
||||
Object.keys(routerConfig).forEach((pageId: string, idx: number) => {
|
||||
if (!pageId) {
|
||||
return;
|
||||
}
|
||||
const path = routerConfig[pageId];
|
||||
routes.push({
|
||||
path,
|
||||
children: (props: any) => this.getLazyComponent(pageId, props),
|
||||
exact: true,
|
||||
defined: { keepAlive: true },
|
||||
});
|
||||
if (homePageId) {
|
||||
return;
|
||||
}
|
||||
if (idx === 0 || path === '/') {
|
||||
homePageId = pageId;
|
||||
}
|
||||
});
|
||||
if (homePageId) {
|
||||
routes.push({
|
||||
path: '**',
|
||||
children: (props: any) => this.getLazyComponent(homePageId, { ...props }),
|
||||
exact: true,
|
||||
defined: { keepAlive: true },
|
||||
});
|
||||
}
|
||||
const RouterView = (props: any) => {
|
||||
return createElement(Router as any, {
|
||||
routes,
|
||||
components: this.getComponents(),
|
||||
utils: this.getUtils(),
|
||||
componentsMap: this.getComponentsMapObj(),
|
||||
...props,
|
||||
});
|
||||
};
|
||||
return RouterView;
|
||||
}
|
||||
|
||||
getLazyComponent(pageId: string, props: any): ReactElement | null {
|
||||
if (!pageId) {
|
||||
return null;
|
||||
}
|
||||
if (this.getlazyElement(pageId)) {
|
||||
return this.getlazyElement(pageId);
|
||||
} else {
|
||||
const lazyElement = createElement(LazyComponent as any, {
|
||||
getPageData: async () => await this.getPageData(pageId),
|
||||
key: pageId,
|
||||
...props,
|
||||
});
|
||||
this.setlazyElement(pageId, lazyElement);
|
||||
return lazyElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
packages/react-provider/tsconfig.json
Normal file
9
packages/react-provider/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"./src/"
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user