feat: 低代码组件支持实时修改属性

This commit is contained in:
wuyue.xht 2021-03-09 19:52:00 +08:00
parent 7168a903ce
commit e7b4e2cc9c
8 changed files with 98 additions and 52 deletions

View File

@ -1,6 +1,6 @@
import { BuiltinSimulatorRenderer, Component, DocumentModel, Node, NodeInstance } from '@ali/lowcode-designer';
import { ComponentSchema, NodeSchema, NpmInfo, RootSchema, TransformStage } from '@ali/lowcode-types';
import { Asset, cursor, isElement, isESModule, isReactComponent, setNativeSelection } from '@ali/lowcode-utils';
import { Asset, compatibleLegaoSchema, cursor, isElement, isESModule, isPlainObject, isReactComponent, setNativeSelection } from '@ali/lowcode-utils';
import LowCodeRenderer from '@ali/lowcode-rax-renderer';
import { computed, obx } from '@recore/obx';
import DriverUniversal from 'driver-universal';
@ -493,7 +493,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
createComponent(schema: NodeSchema): Component | null {
const _schema: any = {
...schema,
...compatibleLegaoSchema(schema),
};
_schema.methods = {};
_schema.lifeCycles = {};
@ -513,8 +513,10 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
class LowCodeComp extends Rax.Component {
render() {
const extraProps = getLowCodeComponentProps(this.props);
// @ts-ignore
return createElement(LowCodeRenderer, {
...extraProps,
schema: _schema,
components,
designMode: renderer.designMode,
@ -620,4 +622,18 @@ function findComponent(libraryMap: LibraryMap, componentName: string, npm?: NpmI
return getSubComponent(library, paths);
}
function getLowCodeComponentProps(props: any) {
if (!props || !isPlainObject(props)) {
return props;
}
const newProps: any = {};
Object.keys(props).forEach(k => {
if (['children', 'componentId', '__designMode', '_componentName', '_leaf'].includes(k)) {
return;
}
newProps[k] = props[k];
});
return newProps;
}
export default new SimulatorRendererContainer();

View File

@ -12,6 +12,8 @@ import {
setNativeSelection,
buildComponents,
getSubComponent,
compatibleLegaoSchema,
isPlainObject,
} from '@ali/lowcode-utils';
import { RootSchema, ComponentSchema, TransformStage, NodeSchema } from '@ali/lowcode-types';
// import { isESModule, isElement, acceptsRef, wrapReactClass, cursor, setNativeSelection } from '@ali/lowcode-utils';
@ -396,7 +398,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
createComponent(schema: NodeSchema): Component | null {
const _schema: any = {
...schema,
...compatibleLegaoSchema(schema),
};
_schema.methods = {};
_schema.lifeCycles = {};
@ -415,8 +417,10 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
class LowCodeComp extends React.Component {
render() {
const extraProps = getLowCodeComponentProps(this.props);
// @ts-ignore
return createElement(LowCodeRenderer, {
...extraProps, // 防止覆盖下面内置属性
schema: _schema,
components,
designMode: renderer.designMode,
@ -543,4 +547,18 @@ function checkInstanceMounted(instance: any): boolean {
return true;
}
function getLowCodeComponentProps(props: any) {
if (!props || !isPlainObject(props)) {
return props;
}
const newProps: any = {};
Object.keys(props).forEach(k => {
if (['children', 'componentId', '__designMode', '_componentName', '_leaf'].includes(k)) {
return;
}
newProps[k] = props[k];
});
return newProps;
}
export default new SimulatorRendererContainer();

View File

@ -412,7 +412,7 @@ export function parseData(schema: any, self: any): any {
return schema;
}
/* 全匹配{{开头,}}结尾的变量表达式或者对象类型JSExpression且均不支持省略this */
/* 全匹配{{开头,}}结尾的变量表达式或者对象类型JSExpression支持省略this */
export function parseExpression(str: any, self: any) {
try {
const contextArr = ['"use strict";', 'var __self = arguments[0];'];
@ -431,7 +431,8 @@ export function parseExpression(str: any, self: any) {
if (inSameDomain() && (window.parent as any).__newFunc) {
return (window.parent as any).__newFunc(tarStr)(self);
}
return new Function(tarStr)(self);
const code = `with($scope || {}) { ${tarStr} }`;
return new Function('$scope', code)(self);
} catch (err) {
debug('parseExpression.error', err, str, self);
return undefined;

View File

@ -21,3 +21,4 @@ export * from './unique-id';
export * from './build-components';
export * from './appHelper';
export * from './misc';
export * from './schema';

View File

@ -2,6 +2,15 @@
import { isI18NObject } from './is-object';
import get from 'lodash.get';
import { ComponentMeta } from '@ali/lowcode-designer';
interface Variable {
type: 'variable';
variable: string;
value: any;
}
export function isVariable(obj: any): obj is Variable {
return obj && obj.type === 'variable';
}
export function isUseI18NSetter(prototype: any, propName: string) {
const configure = prototype?.options?.configure;

View File

@ -0,0 +1,45 @@
import { isJSBlock } from '@ali/lowcode-types';
import { isVariable } from './misc';
import { isPlainObject } from './is-plain-object';
export function compatibleLegaoSchema(props: any) {
if (!props) {
return props;
}
if (Array.isArray(props)) {
return props.map(k => compatibleLegaoSchema(k));
}
if (!isPlainObject(props)) {
return props;
}
if (isJSBlock(props)) {
if (props.value.componentName === 'Slot') {
return {
type: 'JSSlot',
title: (props.value.props as any)?.slotTitle,
name: (props.value.props as any)?.slotName,
value: props.value.children,
};
} else {
return props.value;
}
}
if (isVariable(props)) {
return {
type: 'JSExpression',
value: props.variable,
mock: props.value,
};
}
const newProps: any = {};
Object.keys(props).forEach((key) => {
if (/^__slot__/.test(key) && props[key] === true) {
return;
}
newProps[key] = compatibleLegaoSchema(props[key]);
});
return newProps;
}

View File

@ -1,45 +1,10 @@
import {
isPlainObject,
} from '@ali/lowcode-utils';
import { Node } from '@ali/lowcode-designer';
import { isJSBlock } from '@ali/lowcode-types';
import { isVariable } from '../utils';
import { compatibleLegaoSchema } from '@ali/lowcode-utils';
import { designerCabin } from '@ali/lowcode-engine';
const { getConvertedExtraKey } = designerCabin;
export function upgradePropsReducer(props: any) {
if (!props || !isPlainObject(props)) {
return props;
}
if (isJSBlock(props)) {
if (props.value.componentName === 'Slot') {
return {
type: 'JSSlot',
title: (props.value.props as any)?.slotTitle,
name: (props.value.props as any)?.slotName,
value: props.value.children,
};
} else {
return props.value;
}
}
if (isVariable(props)) {
return {
type: 'JSExpression',
value: props.variable,
mock: props.value,
};
}
const newProps: any = {};
Object.keys(props).forEach((key) => {
if (/^__slot__/.test(key) && props[key] === true) {
return;
}
newProps[key] = upgradePropsReducer(props[key]);
});
return newProps;
}
export const upgradePropsReducer = compatibleLegaoSchema;
export function upgradePageLifeCyclesReducer(props: any, node: Node) {
const lifeCycleNames = ['didMount', 'willUnmount'];

View File

@ -1,14 +1,5 @@
import { designer } from '@ali/lowcode-engine';
interface Variable {
type: 'variable';
variable: string;
value: any;
}
export function isVariable(obj: any): obj is Variable {
return obj && obj.type === 'variable';
}
export { isVariable } from '@ali/lowcode-utils';
export function getCurrentFieldIds() {
const fieldIds: any = [];