mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-16 11:54:27 +00:00
feat: support prop.autorun
This commit is contained in:
parent
8f1a9de33b
commit
c0a523584e
@ -1,4 +1,4 @@
|
|||||||
import { obx, computed } from '@ali/lowcode-editor-core';
|
import { obx, computed, autorun } from '@ali/lowcode-editor-core';
|
||||||
import {
|
import {
|
||||||
isDOMText,
|
isDOMText,
|
||||||
isJSExpression,
|
isJSExpression,
|
||||||
@ -155,17 +155,29 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children));
|
this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children));
|
||||||
this._children.interalInitParent();
|
this._children.interalInitParent();
|
||||||
this.props.import(this.transformProps(props || {}), extras);
|
this.props.import(this.transformProps(props || {}), extras);
|
||||||
|
this.setupAutoruns();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private transformProps(props: any): any {
|
private transformProps(props: any): any {
|
||||||
// FIXME! support PropsList
|
// FIXME! support PropsList
|
||||||
const x = this.document.designer.transformProps(props, this, TransformStage.Init);
|
return this.document.designer.transformProps(props, this, TransformStage.Init);
|
||||||
|
|
||||||
return x;
|
|
||||||
// TODO: run transducers in metadata.experimental
|
// TODO: run transducers in metadata.experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private autoruns?: Array<() => void>;
|
||||||
|
private setupAutoruns() {
|
||||||
|
const autoruns = this.componentMeta.getMetadata().experimental?.autoruns;
|
||||||
|
if (!autoruns || autoruns.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.autoruns = autoruns.map(item => {
|
||||||
|
return autorun(() => {
|
||||||
|
item.autorun(this.props.get(item.name, true) as any)
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private initialChildren(children: any): NodeData[] {
|
private initialChildren(children: any): NodeData[] {
|
||||||
// FIXME! this is dirty code
|
// FIXME! this is dirty code
|
||||||
if (children == null) {
|
if (children == null) {
|
||||||
@ -591,6 +603,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
if (this.isParental()) {
|
if (this.isParental()) {
|
||||||
this.children.purge();
|
this.children.purge();
|
||||||
}
|
}
|
||||||
|
this.autoruns?.forEach(dispose => dispose());
|
||||||
this.props.purge();
|
this.props.purge();
|
||||||
this.document.internalRemoveAndPurgeNode(this);
|
this.document.internalRemoveAndPurgeNode(this);
|
||||||
}
|
}
|
||||||
@ -608,7 +621,16 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
insertBefore(node: Node, ref?: Node) {
|
insertBefore(node: Node, ref?: Node) {
|
||||||
this.children?.insert(node, ref ? ref.index : null);
|
this.children?.insert(node, ref ? ref.index : null);
|
||||||
}
|
}
|
||||||
insertAfter(node: Node, ref?: Node) {
|
insertAfter(node: any, ref?: Node) {
|
||||||
|
if (!isNode(node)) {
|
||||||
|
if (node.getComponentName) {
|
||||||
|
node = this.document.createNode({
|
||||||
|
componentName: node.getComponentName(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
node = this.document.createNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.children?.insert(node, ref ? ref.index + 1 : null);
|
this.children?.insert(node, ref ? ref.index + 1 : null);
|
||||||
}
|
}
|
||||||
getParent() {
|
getParent() {
|
||||||
@ -687,6 +709,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
getSuitablePlace(node: Node, ref: any): any {
|
getSuitablePlace(node: Node, ref: any): any {
|
||||||
|
// TODO:
|
||||||
if (this.isRoot()) {
|
if (this.isRoot()) {
|
||||||
return { container: this, ref };
|
return { container: this, ref };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { obx, autorun, untracked, computed } from '@ali/lowcode-editor-core';
|
import { obx, autorun, untracked, computed } from '@ali/lowcode-editor-core';
|
||||||
import { Prop, IPropParent, UNSET } from './prop';
|
import { Prop, IPropParent, UNSET } from './prop';
|
||||||
import { Props } from './props';
|
import { Props } from './props';
|
||||||
|
import { Node } from '../node';
|
||||||
|
|
||||||
export type PendingItem = Prop[];
|
export type PendingItem = Prop[];
|
||||||
export class PropStash implements IPropParent {
|
export class PropStash implements IPropParent {
|
||||||
@ -15,8 +16,10 @@ export class PropStash implements IPropParent {
|
|||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
private willPurge: () => void;
|
private willPurge: () => void;
|
||||||
|
readonly owner: Node;
|
||||||
|
|
||||||
constructor(readonly props: Props, write: (item: Prop) => void) {
|
constructor(readonly props: Props, write: (item: Prop) => void) {
|
||||||
|
this.owner = props.owner;
|
||||||
this.willPurge = autorun(() => {
|
this.willPurge = autorun(() => {
|
||||||
if (this.space.size < 1) {
|
if (this.space.size < 1) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { uniqueId, isPlainObject, hasOwnProperty } from '@ali/lowcode-utils';
|
|||||||
import { PropStash } from './prop-stash';
|
import { PropStash } from './prop-stash';
|
||||||
import { valueToSource } from './value-to-source';
|
import { valueToSource } from './value-to-source';
|
||||||
import { Props } from './props';
|
import { Props } from './props';
|
||||||
import { SlotNode } from '../node';
|
import { SlotNode, Node } from '../node';
|
||||||
import { TransformStage } from '../transform-stage';
|
import { TransformStage } from '../transform-stage';
|
||||||
|
|
||||||
export const UNSET = Symbol.for('unset');
|
export const UNSET = Symbol.for('unset');
|
||||||
@ -13,12 +13,14 @@ export type UNSET = typeof UNSET;
|
|||||||
export interface IPropParent {
|
export interface IPropParent {
|
||||||
delete(prop: Prop): void;
|
delete(prop: Prop): void;
|
||||||
readonly props: Props;
|
readonly props: Props;
|
||||||
|
readonly owner: Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ValueTypes = 'unset' | 'literal' | 'map' | 'list' | 'expression' | 'slot';
|
export type ValueTypes = 'unset' | 'literal' | 'map' | 'list' | 'expression' | 'slot';
|
||||||
|
|
||||||
export class Prop implements IPropParent {
|
export class Prop implements IPropParent {
|
||||||
readonly isProp = true;
|
readonly isProp = true;
|
||||||
|
readonly owner: Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SettingTarget
|
* @see SettingTarget
|
||||||
@ -350,6 +352,7 @@ export class Prop implements IPropParent {
|
|||||||
key?: string | number,
|
key?: string | number,
|
||||||
spread = false,
|
spread = false,
|
||||||
) {
|
) {
|
||||||
|
this.owner = parent.owner;
|
||||||
this.props = parent.props;
|
this.props = parent.props;
|
||||||
if (value !== UNSET) {
|
if (value !== UNSET) {
|
||||||
this.setValue(value);
|
this.setValue(value);
|
||||||
@ -613,6 +616,10 @@ export class Prop implements IPropParent {
|
|||||||
getProps() {
|
getProps() {
|
||||||
return this.parent;
|
return this.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNode() {
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isProp(obj: any): obj is Prop {
|
export function isProp(obj: any): obj is Prop {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
|
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
|
||||||
import { isPlainObject } from '@ali/lowcode-utils';
|
import { isPlainObject } from '@ali/lowcode-utils';
|
||||||
import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, isJSExpression } from '@ali/lowcode-types';
|
import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, isJSExpression, AutorunItem } from '@ali/lowcode-types';
|
||||||
|
import { untracked } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
type Field = SettingTarget;
|
type Field = SettingTarget;
|
||||||
|
|
||||||
@ -290,19 +291,44 @@ export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollec
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessor && !slotName) {
|
if (!slotName) {
|
||||||
|
if (accessor) {
|
||||||
extraProps.getValue = (field: Field, fieldValue: any) => {
|
extraProps.getValue = (field: Field, fieldValue: any) => {
|
||||||
return accessor.call(field, fieldValue);
|
return accessor.call(field, fieldValue);
|
||||||
};
|
};
|
||||||
if (!initialFn) {
|
}
|
||||||
initialFn = accessor;
|
|
||||||
|
if (sync || accessor) {
|
||||||
|
collector.addAutorun({
|
||||||
|
name,
|
||||||
|
autorun: (field: Field) => {
|
||||||
|
let fieldValue = untracked(() => field.getValue());
|
||||||
|
if (accessor) {
|
||||||
|
fieldValue = accessor.call(field, fieldValue)
|
||||||
|
}
|
||||||
|
if (sync) {
|
||||||
|
fieldValue = sync.call(field, fieldValue);
|
||||||
|
if (fieldValue !== undefined) {
|
||||||
|
field.setValue(fieldValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
field.setValue(fieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutator) {
|
||||||
|
extraProps.setValue = (field: Field, value: any) => {
|
||||||
|
mutator.call(field, value, value);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setterInitial = getInitialFromSetter(setter);
|
const setterInitial = getInitialFromSetter(setter);
|
||||||
|
|
||||||
collector.addInitial({
|
collector.addInitial({
|
||||||
// FIXME! name should be "xxx.xxx"
|
// FIXME! name could be "xxx.xxx"
|
||||||
name: slotName || name,
|
name: slotName || name,
|
||||||
initial: (field: Field, currentValue: any) => {
|
initial: (field: Field, currentValue: any) => {
|
||||||
// FIXME! read from prototype.defaultProps
|
// FIXME! read from prototype.defaultProps
|
||||||
@ -345,20 +371,6 @@ export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollec
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sync) {
|
|
||||||
extraProps.autorun = (field: Field) => {
|
|
||||||
const value = sync.call(field, field.getValue());
|
|
||||||
if (value !== undefined) {
|
|
||||||
field.setValue(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (mutator && !slotName) {
|
|
||||||
extraProps.setValue = (field: Field, value: any) => {
|
|
||||||
mutator.call(field, value, value);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slotName) {
|
if (slotName) {
|
||||||
newConfig.name = slotName;
|
newConfig.name = slotName;
|
||||||
if (!newConfig.title && slotTitle) {
|
if (!newConfig.title && slotTitle) {
|
||||||
@ -396,7 +408,6 @@ export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollec
|
|||||||
let primarySetter: any;
|
let primarySetter: any;
|
||||||
if (type === 'composite') {
|
if (type === 'composite') {
|
||||||
const initials: InitialItem[] = [];
|
const initials: InitialItem[] = [];
|
||||||
const filters: FilterItem[] = [];
|
|
||||||
const objItems = items
|
const objItems = items
|
||||||
? upgradeConfigure(items,
|
? upgradeConfigure(items,
|
||||||
{
|
{
|
||||||
@ -404,8 +415,17 @@ export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollec
|
|||||||
initials.push(item);
|
initials.push(item);
|
||||||
},
|
},
|
||||||
addFilter: (item) => {
|
addFilter: (item) => {
|
||||||
filters.push(item);
|
collector.addFilter({
|
||||||
}
|
name: `${name}.${item.name}`,
|
||||||
|
filter: item.filter,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addAutorun: (item) => {
|
||||||
|
collector.addAutorun({
|
||||||
|
name: `${name}.${item.name}`,
|
||||||
|
autorun: item.autorun,
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
@ -481,10 +501,12 @@ export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollec
|
|||||||
|
|
||||||
type AddInitial = (initialItem: InitialItem) => void;
|
type AddInitial = (initialItem: InitialItem) => void;
|
||||||
type AddFilter = (filterItem: FilterItem) => void;
|
type AddFilter = (filterItem: FilterItem) => void;
|
||||||
|
type AddAutorun = (autorunItem: AutorunItem) => void;
|
||||||
|
|
||||||
type ConfigCollector = {
|
type ConfigCollector = {
|
||||||
addInitial: AddInitial,
|
addInitial: AddInitial;
|
||||||
addFilter: AddFilter,
|
addFilter: AddFilter;
|
||||||
|
addAutorun: AddAutorun;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitialFromSetter(setter: any) {
|
function getInitialFromSetter(setter: any) {
|
||||||
@ -750,6 +772,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
|||||||
|
|
||||||
const initials: InitialItem[] = [];
|
const initials: InitialItem[] = [];
|
||||||
const filters: FilterItem[] = [];
|
const filters: FilterItem[] = [];
|
||||||
|
const autoruns: AutorunItem[] = [];
|
||||||
const props = upgradeConfigure(configure || [],
|
const props = upgradeConfigure(configure || [],
|
||||||
{
|
{
|
||||||
addInitial: (item) => {
|
addInitial: (item) => {
|
||||||
@ -758,10 +781,14 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
|||||||
addFilter: (item) => {
|
addFilter: (item) => {
|
||||||
filters.push(item);
|
filters.push(item);
|
||||||
},
|
},
|
||||||
|
addAutorun: (item) => {
|
||||||
|
autoruns.push(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
experimental.initials = initials;
|
experimental.initials = initials;
|
||||||
experimental.filters = filters;
|
experimental.filters = filters;
|
||||||
|
experimental.autoruns = autoruns;
|
||||||
|
|
||||||
const supports: any = {};
|
const supports: any = {};
|
||||||
if (canUseCondition != null) {
|
if (canUseCondition != null) {
|
||||||
|
|||||||
@ -49,6 +49,11 @@ export interface FilterItem {
|
|||||||
name: string;
|
name: string;
|
||||||
filter: (target: SettingTarget, currentValue: any) => any;
|
filter: (target: SettingTarget, currentValue: any) => any;
|
||||||
}
|
}
|
||||||
|
export interface AutorunItem {
|
||||||
|
name: string;
|
||||||
|
autorun: (target: SettingTarget) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Experimental {
|
export interface Experimental {
|
||||||
context?: { [contextInfoName: string]: any };
|
context?: { [contextInfoName: string]: any };
|
||||||
@ -57,8 +62,8 @@ export interface Experimental {
|
|||||||
transducers?: any; // ? should support
|
transducers?: any; // ? should support
|
||||||
initials?: InitialItem[];
|
initials?: InitialItem[];
|
||||||
filters?: FilterItem[];
|
filters?: FilterItem[];
|
||||||
|
autoruns?: AutorunItem[];
|
||||||
callbacks?: Callbacks;
|
callbacks?: Callbacks;
|
||||||
// TODO: thinkof function
|
|
||||||
initialChildren?: NodeData[] | ((target: SettingTarget) => NodeData[]);
|
initialChildren?: NodeData[] | ((target: SettingTarget) => NodeData[]);
|
||||||
|
|
||||||
// 样式 及 位置,handle上必须有明确的标识以便事件路由判断,或者主动设置事件独占模式
|
// 样式 及 位置,handle上必须有明确的标识以便事件路由判断,或者主动设置事件独占模式
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user