@alilc/lowcode-renderer-core
Version:
renderer core
521 lines (513 loc) • 24.6 kB
JavaScript
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
import _extends from "@babel/runtime/helpers/extends";
import _createClass from "@babel/runtime/helpers/createClass";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
var _excluded = ["visible"],
_excluded2 = ["forwardedRef"];
import { GlobalEvent, IPublicEnumTransformStage } from '@alilc/lowcode-types';
import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils';
import { debounce } from '../utils/common';
import adapter from '../adapter';
import logger from '../utils/logger';
var RerenderType = /*#__PURE__*/function (RerenderType) {
RerenderType["All"] = "All";
RerenderType["ChildChanged"] = "ChildChanged";
RerenderType["PropsChanged"] = "PropsChanged";
RerenderType["VisibleChanged"] = "VisibleChanged";
RerenderType["MinimalRenderUnit"] = "MinimalRenderUnit";
return RerenderType;
}(RerenderType || {}); // 缓存 Leaf 层组件,防止重新渲染问题
var LeafCache = function LeafCache(documentId, device) {
this.documentId = documentId;
this.device = device;
/** 组件缓存 */
this.component = new Map();
/**
* 状态缓存,场景:属性变化后,改组件被销毁,state 为空,没有展示修改后的属性
*/
this.state = new Map();
/**
* 订阅事件缓存,导致 rerender 的订阅事件
*/
this.event = new Map();
this.ref = new Map();
};
var cache;
/** 部分没有渲染的 node 节点进行兜底处理 or 渲染方式没有渲染 LeafWrapper */
function initRerenderEvent(_ref) {
var _cache$event$get, _cache$event$get2, _leaf$onPropChange, _leaf$onChildrenChang, _leaf$onVisibleChange;
var schema = _ref.schema,
__debug = _ref.__debug,
container = _ref.container,
getNode = _ref.getNode;
var leaf = getNode === null || getNode === void 0 ? void 0 : getNode(schema.id);
if (!leaf || (_cache$event$get = cache.event.get(schema.id)) !== null && _cache$event$get !== void 0 && _cache$event$get.clear || leaf === cache.event.get(schema.id)) {
return;
}
(_cache$event$get2 = cache.event.get(schema.id)) === null || _cache$event$get2 === void 0 ? void 0 : _cache$event$get2.dispose.forEach(function (disposeFn) {
return disposeFn && disposeFn();
});
var debounceRerender = debounce(function () {
container.rerender();
}, 20);
cache.event.set(schema.id, {
clear: false,
leaf: leaf,
dispose: [leaf === null || leaf === void 0 ? void 0 : (_leaf$onPropChange = leaf.onPropChange) === null || _leaf$onPropChange === void 0 ? void 0 : _leaf$onPropChange.call(leaf, function () {
if (!container.autoRepaintNode) {
return;
}
__debug(schema.componentName + "[" + schema.id + "] leaf not render in SimulatorRendererView, leaf onPropsChange make rerender");
debounceRerender();
}), leaf === null || leaf === void 0 ? void 0 : (_leaf$onChildrenChang = leaf.onChildrenChange) === null || _leaf$onChildrenChang === void 0 ? void 0 : _leaf$onChildrenChang.call(leaf, function () {
if (!container.autoRepaintNode) {
return;
}
__debug(schema.componentName + "[" + schema.id + "] leaf not render in SimulatorRendererView, leaf onChildrenChange make rerender");
debounceRerender();
}), leaf === null || leaf === void 0 ? void 0 : (_leaf$onVisibleChange = leaf.onVisibleChange) === null || _leaf$onVisibleChange === void 0 ? void 0 : _leaf$onVisibleChange.call(leaf, function () {
if (!container.autoRepaintNode) {
return;
}
__debug(schema.componentName + "[" + schema.id + "] leaf not render in SimulatorRendererView, leaf onVisibleChange make rerender");
debounceRerender();
})]
});
}
/** 渲染的 node 节点全局注册事件清除 */
function clearRerenderEvent(id) {
var _cache$event$get3, _cache$event$get4, _cache$event$get4$dis;
if ((_cache$event$get3 = cache.event.get(id)) !== null && _cache$event$get3 !== void 0 && _cache$event$get3.clear) {
return;
}
(_cache$event$get4 = cache.event.get(id)) === null || _cache$event$get4 === void 0 ? void 0 : (_cache$event$get4$dis = _cache$event$get4.dispose) === null || _cache$event$get4$dis === void 0 ? void 0 : _cache$event$get4$dis.forEach(function (disposeFn) {
return disposeFn && disposeFn();
});
cache.event.set(id, {
clear: true,
dispose: []
});
}
// 给每个组件包裹一个 HOC Leaf,支持组件内部属性变化,自响应渲染
export function leafWrapper(Comp, _ref2) {
var _baseRenderer$props, _baseRenderer$props$d, _baseRenderer$props2, _baseRenderer$props$d2, _baseRenderer$props3, _baseRenderer$props4, _baseRenderer$props5, _baseRenderer$props6, _host$designer;
var schema = _ref2.schema,
baseRenderer = _ref2.baseRenderer,
componentInfo = _ref2.componentInfo,
scope = _ref2.scope;
var __debug = baseRenderer.__debug,
getProps = baseRenderer.__getComponentProps,
getChildren = baseRenderer.__getSchemaChildrenVirtualDom,
__parseData = baseRenderer.__parseData;
var engine = baseRenderer.context.engine;
var host = (_baseRenderer$props = baseRenderer.props) === null || _baseRenderer$props === void 0 ? void 0 : _baseRenderer$props.__host;
var curDocumentId = (_baseRenderer$props$d = (_baseRenderer$props2 = baseRenderer.props) === null || _baseRenderer$props2 === void 0 ? void 0 : _baseRenderer$props2.documentId) !== null && _baseRenderer$props$d !== void 0 ? _baseRenderer$props$d : '';
var curDevice = (_baseRenderer$props$d2 = (_baseRenderer$props3 = baseRenderer.props) === null || _baseRenderer$props3 === void 0 ? void 0 : _baseRenderer$props3.device) !== null && _baseRenderer$props$d2 !== void 0 ? _baseRenderer$props$d2 : '';
var getNode = (_baseRenderer$props4 = baseRenderer.props) === null || _baseRenderer$props4 === void 0 ? void 0 : _baseRenderer$props4.getNode;
var container = (_baseRenderer$props5 = baseRenderer.props) === null || _baseRenderer$props5 === void 0 ? void 0 : _baseRenderer$props5.__container;
var setSchemaChangedSymbol = (_baseRenderer$props6 = baseRenderer.props) === null || _baseRenderer$props6 === void 0 ? void 0 : _baseRenderer$props6.setSchemaChangedSymbol;
var editor = host === null || host === void 0 ? void 0 : (_host$designer = host.designer) === null || _host$designer === void 0 ? void 0 : _host$designer.editor;
var runtime = adapter.getRuntime();
var forwardRef = runtime.forwardRef,
createElement = runtime.createElement;
var Component = runtime.Component;
var componentCacheId = schema.id;
if (!cache || curDocumentId && curDocumentId !== cache.documentId || curDevice && curDevice !== cache.device) {
var _cache;
(_cache = cache) === null || _cache === void 0 ? void 0 : _cache.event.forEach(function (event) {
var _event$dispose;
(_event$dispose = event.dispose) === null || _event$dispose === void 0 ? void 0 : _event$dispose.forEach(function (disposeFn) {
return disposeFn && disposeFn();
});
});
cache = new LeafCache(curDocumentId, curDevice);
}
if (!isReactComponent(Comp)) {
logger.error(schema.componentName + " component may be has errors: ", Comp);
}
initRerenderEvent({
schema: schema,
__debug: __debug,
container: container,
getNode: getNode
});
if (curDocumentId && cache.component.has(componentCacheId) && cache.component.get(componentCacheId).Comp === Comp) {
return cache.component.get(componentCacheId).LeafWrapper;
}
var LeafHoc = /*#__PURE__*/function (_Component) {
function LeafHoc(props, context) {
var _this;
_this = _Component.call(this, props, context) || this;
// 监听以下事件,当变化时更新自己
_this.recordInfo = {};
_this.curEventLeaf = void 0;
_this.disposeFunctions = [];
_this.__component_tag = 'leafWrapper';
_this.renderUnitInfo = void 0;
// 最小渲染单元做防抖处理
_this.makeUnitRenderDebounced = debounce(function () {
var _this$leaf, _this$leaf$export, _this$leaf2;
_this.beforeRender(RerenderType.MinimalRenderUnit);
var schema = (_this$leaf = _this.leaf) === null || _this$leaf === void 0 ? void 0 : (_this$leaf$export = _this$leaf["export"]) === null || _this$leaf$export === void 0 ? void 0 : _this$leaf$export.call(_this$leaf, IPublicEnumTransformStage.Render);
if (!schema) {
return;
}
var nextProps = getProps(schema, scope, Comp, componentInfo);
var children = getChildren(schema, scope, Comp);
var nextState = {
nodeProps: nextProps,
nodeChildren: children,
childrenInState: true
};
if ('children' in nextProps) {
nextState.nodeChildren = nextProps.children;
}
__debug(((_this$leaf2 = _this.leaf) === null || _this$leaf2 === void 0 ? void 0 : _this$leaf2.componentName) + "(" + _this.props.componentId + ") MinimalRenderUnit Render!");
_this.setState(nextState);
}, 20);
_this.recordTime = function () {
var _host$designer2, _host$designer2$curre, _host$designer2$curre2, _this$recordInfo$node, _this$leaf3;
if (!_this.recordInfo.startTime) {
return;
}
var endTime = Date.now();
var nodeCount = host === null || host === void 0 ? void 0 : (_host$designer2 = host.designer) === null || _host$designer2 === void 0 ? void 0 : (_host$designer2$curre = _host$designer2.currentDocument) === null || _host$designer2$curre === void 0 ? void 0 : (_host$designer2$curre2 = _host$designer2$curre.getNodeCount) === null || _host$designer2$curre2 === void 0 ? void 0 : _host$designer2$curre2.call(_host$designer2$curre);
var componentName = ((_this$recordInfo$node = _this.recordInfo.node) === null || _this$recordInfo$node === void 0 ? void 0 : _this$recordInfo$node.componentName) || ((_this$leaf3 = _this.leaf) === null || _this$leaf3 === void 0 ? void 0 : _this$leaf3.componentName) || 'UnknownComponent';
editor === null || editor === void 0 ? void 0 : editor.eventBus.emit(GlobalEvent.Node.Rerender, {
componentName: componentName,
time: endTime - _this.recordInfo.startTime,
type: _this.recordInfo.type,
nodeCount: nodeCount
});
_this.recordInfo.startTime = null;
};
_this.makeUnitRender = function () {
_this.makeUnitRenderDebounced();
};
__debug(schema.componentName + "[" + _this.props.componentId + "] leaf render in SimulatorRendererView");
clearRerenderEvent(componentCacheId);
_this.curEventLeaf = _this.leaf;
cache.ref.set(componentCacheId, {
makeUnitRender: _this.makeUnitRender
});
var cacheState = cache.state.get(componentCacheId);
if (!cacheState || cacheState.__tag !== props.__tag) {
cacheState = _this.getDefaultState(props);
}
_this.state = cacheState;
return _this;
}
_inheritsLoose(LeafHoc, _Component);
var _proto = LeafHoc.prototype;
_proto.componentDidUpdate = function componentDidUpdate() {
this.recordTime();
};
_proto.componentDidMount = function componentDidMount() {
var _leaf = this.leaf;
this.initOnPropsChangeEvent(_leaf);
this.initOnChildrenChangeEvent(_leaf);
this.initOnVisibleChangeEvent(_leaf);
this.recordTime();
};
_proto.getDefaultState = function getDefaultState(nextProps) {
var _this$leaf4, _this$leaf4$export;
var _ref3 = nextProps.__inner__ || ((_this$leaf4 = this.leaf) === null || _this$leaf4 === void 0 ? void 0 : (_this$leaf4$export = _this$leaf4["export"]) === null || _this$leaf4$export === void 0 ? void 0 : _this$leaf4$export.call(_this$leaf4, IPublicEnumTransformStage.Render)) || {},
_ref3$hidden = _ref3.hidden,
hidden = _ref3$hidden === void 0 ? false : _ref3$hidden,
_ref3$condition = _ref3.condition,
condition = _ref3$condition === void 0 ? true : _ref3$condition;
return {
nodeChildren: null,
childrenInState: false,
visible: !hidden,
condition: __parseData === null || __parseData === void 0 ? void 0 : __parseData(condition, scope),
nodeCacheProps: {},
nodeProps: {}
};
};
_proto.setState = function setState(state) {
cache.state.set(componentCacheId, _extends({}, this.state, state, {
__tag: this.props.__tag
}));
_Component.prototype.setState.call(this, state);
}
/** 由于内部属性变化,在触发渲染前,会执行该函数 */;
_proto.beforeRender = function beforeRender(type, node) {
this.recordInfo.startTime = Date.now();
this.recordInfo.type = type;
this.recordInfo.node = node;
setSchemaChangedSymbol === null || setSchemaChangedSymbol === void 0 ? void 0 : setSchemaChangedSymbol(true);
};
_proto.judgeMiniUnitRender = function judgeMiniUnitRender() {
var _this$leaf5;
if (!this.renderUnitInfo) {
this.getRenderUnitInfo();
}
var renderUnitInfo = this.renderUnitInfo || {
singleRender: true
};
if (renderUnitInfo.singleRender) {
return;
}
var ref = cache.ref.get(renderUnitInfo.minimalUnitId);
if (!ref) {
__debug('Cant find minimalRenderUnit ref! This make rerender!');
container === null || container === void 0 ? void 0 : container.rerender();
return;
}
__debug(((_this$leaf5 = this.leaf) === null || _this$leaf5 === void 0 ? void 0 : _this$leaf5.componentName) + "(" + this.props.componentId + ") need render, make its minimalRenderUnit " + renderUnitInfo.minimalUnitName + "(" + renderUnitInfo.minimalUnitId + ")");
ref.makeUnitRender();
};
_proto.getRenderUnitInfo = function getRenderUnitInfo(leaf) {
if (leaf === void 0) {
leaf = this.leaf;
}
// leaf 在低代码组件中存在 mock 的情况,退出最小渲染单元判断
if (!leaf || typeof leaf.isRoot !== 'function') {
return;
}
if (leaf.isRootNode) {
this.renderUnitInfo = _extends({
singleRender: true
}, this.renderUnitInfo || {});
}
if (leaf.componentMeta.isMinimalRenderUnit) {
this.renderUnitInfo = {
minimalUnitId: leaf.id,
minimalUnitName: leaf.componentName,
singleRender: false
};
}
if (leaf.hasLoop()) {
var _leaf2, _leaf2$parent, _leaf3, _leaf3$parent;
// 含有循环配置的元素,父元素是最小渲染单元
this.renderUnitInfo = {
minimalUnitId: (_leaf2 = leaf) === null || _leaf2 === void 0 ? void 0 : (_leaf2$parent = _leaf2.parent) === null || _leaf2$parent === void 0 ? void 0 : _leaf2$parent.id,
minimalUnitName: (_leaf3 = leaf) === null || _leaf3 === void 0 ? void 0 : (_leaf3$parent = _leaf3.parent) === null || _leaf3$parent === void 0 ? void 0 : _leaf3$parent.componentName,
singleRender: false
};
}
if (leaf.parent) {
this.getRenderUnitInfo(leaf.parent);
}
};
_proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
var componentId = nextProps.componentId;
if (nextProps.__tag === this.props.__tag) {
return null;
}
var _leaf = getNode === null || getNode === void 0 ? void 0 : getNode(componentId);
if (_leaf && this.curEventLeaf && _leaf !== this.curEventLeaf) {
this.disposeFunctions.forEach(function (fn) {
return fn();
});
this.disposeFunctions = [];
this.initOnChildrenChangeEvent(_leaf);
this.initOnPropsChangeEvent(_leaf);
this.initOnVisibleChangeEvent(_leaf);
this.curEventLeaf = _leaf;
}
var _this$getDefaultState = this.getDefaultState(nextProps),
visible = _this$getDefaultState.visible,
resetState = _objectWithoutPropertiesLoose(_this$getDefaultState, _excluded);
this.setState(resetState);
}
/** 监听参数变化 */;
_proto.initOnPropsChangeEvent = function initOnPropsChangeEvent(leaf) {
var _this2 = this,
_leaf5,
_leaf5$onPropChange;
if (leaf === void 0) {
leaf = this.leaf;
}
var handlePropsChange = debounce(function (propChangeInfo) {
var _node$export, _leaf4;
var key = propChangeInfo.key,
_propChangeInfo$newVa = propChangeInfo.newValue,
newValue = _propChangeInfo$newVa === void 0 ? null : _propChangeInfo$newVa;
var node = leaf;
if (key === '___condition___') {
var _this2$leaf;
var _ref4 = ((_this2$leaf = _this2.leaf) === null || _this2$leaf === void 0 ? void 0 : _this2$leaf["export"](IPublicEnumTransformStage.Render)) || {},
_ref4$condition = _ref4.condition,
condition = _ref4$condition === void 0 ? true : _ref4$condition;
var conditionValue = __parseData === null || __parseData === void 0 ? void 0 : __parseData(condition, scope);
__debug("key is ___condition___, change condition value to [" + condition + "]");
// 条件表达式改变
_this2.setState({
condition: conditionValue
});
return;
}
// 如果循坏条件变化,从根节点重新渲染
// 目前多层循坏无法判断需要从哪一层开始渲染,故先粗暴解决
if (key === '___loop___') {
__debug('key is ___loop___, render a page!');
container === null || container === void 0 ? void 0 : container.rerender();
// 由于 scope 变化,需要清空缓存,使用新的 scope
cache.component["delete"](componentCacheId);
return;
}
_this2.beforeRender(RerenderType.PropsChanged);
var state = _this2.state;
var nodeCacheProps = state.nodeCacheProps;
var nodeProps = getProps(node === null || node === void 0 ? void 0 : (_node$export = node["export"]) === null || _node$export === void 0 ? void 0 : _node$export.call(node, IPublicEnumTransformStage.Render), scope, Comp, componentInfo);
if (key && !(key in nodeProps) && key in _this2.props) {
// 当 key 在 this.props 中时,且不存在在计算值中,需要用 newValue 覆盖掉 this.props 的取值
nodeCacheProps[key] = newValue;
}
__debug(((_leaf4 = leaf) === null || _leaf4 === void 0 ? void 0 : _leaf4.componentName) + "[" + _this2.props.componentId + "] component trigger onPropsChange!", nodeProps, nodeCacheProps, key, newValue);
_this2.setState('children' in nodeProps ? {
nodeChildren: nodeProps.children,
nodeProps: nodeProps,
childrenInState: true,
nodeCacheProps: nodeCacheProps
} : {
nodeProps: nodeProps,
nodeCacheProps: nodeCacheProps
});
_this2.judgeMiniUnitRender();
});
var dispose = (_leaf5 = leaf) === null || _leaf5 === void 0 ? void 0 : (_leaf5$onPropChange = _leaf5.onPropChange) === null || _leaf5$onPropChange === void 0 ? void 0 : _leaf5$onPropChange.call(_leaf5, function (propChangeInfo) {
if (!_this2.autoRepaintNode) {
return;
}
handlePropsChange(propChangeInfo);
});
dispose && this.disposeFunctions.push(dispose);
}
/**
* 监听显隐变化
*/;
_proto.initOnVisibleChangeEvent = function initOnVisibleChangeEvent(leaf) {
var _leaf6,
_leaf6$onVisibleChang,
_this3 = this;
if (leaf === void 0) {
leaf = this.leaf;
}
var dispose = (_leaf6 = leaf) === null || _leaf6 === void 0 ? void 0 : (_leaf6$onVisibleChang = _leaf6.onVisibleChange) === null || _leaf6$onVisibleChang === void 0 ? void 0 : _leaf6$onVisibleChang.call(_leaf6, function (flag) {
var _leaf7;
if (!_this3.autoRepaintNode) {
return;
}
if (_this3.state.visible === flag) {
return;
}
__debug(((_leaf7 = leaf) === null || _leaf7 === void 0 ? void 0 : _leaf7.componentName) + "[" + _this3.props.componentId + "] component trigger onVisibleChange(" + flag + ") event");
_this3.beforeRender(RerenderType.VisibleChanged);
_this3.setState({
visible: flag
});
_this3.judgeMiniUnitRender();
});
dispose && this.disposeFunctions.push(dispose);
}
/**
* 监听子元素变化(拖拽,删除...)
*/;
_proto.initOnChildrenChangeEvent = function initOnChildrenChangeEvent(leaf) {
var _leaf8,
_leaf8$onChildrenChan,
_this4 = this;
if (leaf === void 0) {
leaf = this.leaf;
}
var dispose = (_leaf8 = leaf) === null || _leaf8 === void 0 ? void 0 : (_leaf8$onChildrenChan = _leaf8.onChildrenChange) === null || _leaf8$onChildrenChan === void 0 ? void 0 : _leaf8$onChildrenChan.call(_leaf8, function (param) {
var _leaf9, _leaf9$export;
if (!_this4.autoRepaintNode) {
return;
}
var _ref5 = param || {},
type = _ref5.type,
node = _ref5.node;
_this4.beforeRender(RerenderType.ChildChanged + "-" + type, node);
// TODO: 缓存同级其他元素的 children。
// 缓存二级 children Next 查询筛选组件有问题
// 缓存一级 children Next Tab 组件有问题
var nextChild = getChildren((_leaf9 = leaf) === null || _leaf9 === void 0 ? void 0 : (_leaf9$export = _leaf9["export"]) === null || _leaf9$export === void 0 ? void 0 : _leaf9$export.call(_leaf9, IPublicEnumTransformStage.Render), scope, Comp);
__debug(schema.componentName + "[" + _this4.props.componentId + "] component trigger onChildrenChange event", nextChild);
_this4.setState({
nodeChildren: nextChild,
childrenInState: true
});
_this4.judgeMiniUnitRender();
});
dispose && this.disposeFunctions.push(dispose);
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.disposeFunctions.forEach(function (fn) {
return fn();
});
};
_proto.render = function render() {
if (!this.state.visible || !this.state.condition) {
return null;
}
var _this$props = this.props,
forwardedRef = _this$props.forwardedRef,
rest = _objectWithoutPropertiesLoose(_this$props, _excluded2);
var compProps = _extends({}, rest, this.state.nodeCacheProps || {}, this.state.nodeProps || {}, {
children: [],
__id: this.props.componentId,
ref: forwardedRef
});
delete compProps.__inner__;
if (this.hasChildren) {
return engine.createElement(Comp, compProps, this.children);
}
return engine.createElement(Comp, compProps);
};
return _createClass(LeafHoc, [{
key: "autoRepaintNode",
get: function get() {
return container === null || container === void 0 ? void 0 : container.autoRepaintNode;
}
}, {
key: "hasChildren",
get: function get() {
if (!this.state.childrenInState) {
return 'children' in this.props;
}
return true;
}
}, {
key: "children",
get: function get() {
if (this.state.childrenInState) {
return this.state.nodeChildren;
}
if (this.props.children && !Array.isArray(this.props.children)) {
return [this.props.children];
}
if (this.props.children && this.props.children.length) {
return this.props.children;
}
return this.props.children;
}
}, {
key: "leaf",
get: function get() {
var _this$props$_leaf;
if ((_this$props$_leaf = this.props._leaf) !== null && _this$props$_leaf !== void 0 && _this$props$_leaf.isMock) {
// 低代码组件作为一个整体更新,其内部的组件不需要监听相关事件
return undefined;
}
return getNode === null || getNode === void 0 ? void 0 : getNode(componentCacheId);
}
}]);
}(Component);
LeafHoc.displayName = schema.componentName;
var LeafWrapper = forwardRef(function (props, ref) {
return createElement(LeafHoc, _extends({}, props, {
forwardedRef: ref
}));
});
LeafWrapper = cloneEnumerableProperty(LeafWrapper, Comp);
LeafWrapper.displayName = Comp.displayName;
cache.component.set(componentCacheId, {
LeafWrapper: LeafWrapper,
Comp: Comp
});
return LeafWrapper;
}