第144篇:阿里低開專案 init方法

养肥胖虎發表於2024-03-20

好傢伙,

demo-general專案執行後主介面如下

解析阿里低開引擎中的初始化方法init

拆解專案來自阿里的lowcode engine目錄下的 demo general專案

0.找到入口檔案

可以看到整個專案用到的外掛非常之多

於是

  1. init: init 方法用於初始化低程式碼引擎,負責載入各種外掛並配置引擎的執行環境。

  2. plugins: plugins 是一個外掛集合,包含了多個外掛,用於擴充套件低程式碼引擎的功能。

  3. createFetchHandler: createFetchHandler 方法用於建立一個資料來源的處理器,用於處理資料來源相關的操作。

  4. EditorInitPlugin: 編輯器初始化外掛,用於初始化低程式碼引擎的編輯器。

  5. UndoRedoPlugin: 撤銷重做外掛,提供撤銷和重做操作的功能。

  6. ZhEnPlugin: 中英文切換外掛,用於實現介面語言的切換。

  7. CodeGenPlugin: 程式碼生成外掛,用於生成程式碼。

  8. DataSourcePanePlugin: 資料來源皮膚外掛,用於管理資料來源。

  9. SchemaPlugin: Schema 外掛,用於處理資料模型的定義和管理。

  10. CodeEditorPlugin: 程式碼編輯器外掛,用於提供程式碼編輯功能。

  11. ManualPlugin: 手冊外掛,提供使用者手冊和幫助文件。

  12. InjectPlugin: 注入外掛,用於注入特定功能或程式碼。

  13. SimulatorResizerPlugin: 模擬器調整外掛,用於調整模擬器的大小。

  14. ComponentPanelPlugin: 元件皮膚外掛,用於管理可用元件。

  15. DefaultSettersRegistryPlugin: 預設設定註冊外掛,用於註冊預設設定。

  16. LoadIncrementalAssetsWidgetPlugin: 載入增量資源小部件外掛,用於載入增量資源。

  17. SaveSamplePlugin: 儲存示例外掛,用於儲存示例程式碼。

  18. PreviewSamplePlugin: 預覽示例外掛,用於預覽示例程式碼。

  19. CustomSetterSamplePlugin: 自定義設定示例外掛,用於自定義設定示例。

  20. SetRefPropPlugin: 設定引用屬性外掛,用於設定引用屬性。

  21. LogoSamplePlugin: Logo 示例外掛,用於展示 Logo 示例。

  22. SimulatorLocalePlugin: 模擬器語言外掛,用於設定模擬器的語言。

  23. lowcodePlugin: 低程式碼元件外掛,用於提供低程式碼元件功能。

  24. appHelper: 應用程式輔助方法,可能包含一些輔助函式或工具函式。

  25. global.scss: 全域性樣式檔案,定義了全域性的樣式規則

那麼把我們主要要解析的檔案拿出來

就這行

import { init, plugins } from '@alilc/lowcode-engine';

1.官方文件定位包位置

2.在lowcode-engine中尋找init方法

直接找到

engine-core引擎核心,是他沒錯了

我們來看看這段程式碼到底在做什麼?

//engine-core.ts
export async function init( container?: HTMLElement, options?: IPublicTypeEngineOptions, pluginPreference?: PluginPreference, ) { await destroy(); let engineOptions = null; if (isPlainObject(container)) { engineOptions = container; engineContainer = document.createElement('div'); engineContainer.id = 'engine'; document.body.appendChild(engineContainer); } else { engineOptions = options; engineContainer = container; if (!container) { engineContainer = document.createElement('div'); engineContainer.id = 'engine'; document.body.appendChild(engineContainer); } } engineConfig.setEngineOptions(engineOptions as any); const { Workbench } = common.skeletonCabin; if (options && options.enableWorkspaceMode) { const disposeFun = await pluginPromise; disposeFun && disposeFun(); render( createElement(WorkSpaceWorkbench, { workspace: innerWorkspace, // skeleton: workspace.skeleton, className: 'engine-main', topAreaItemClassName: 'engine-actionitem', }), engineContainer, ); innerWorkspace.enableAutoOpenFirstWindow = engineConfig.get('enableAutoOpenFirstWindow', true); innerWorkspace.setActive(true); innerWorkspace.initWindow(); innerHotkey.activate(false); await innerWorkspace.plugins.init(pluginPreference); return; } await plugins.init(pluginPreference as any); render( createElement(Workbench, { skeleton: innerSkeleton, className: 'engine-main', topAreaItemClassName: 'engine-actionitem', }), engineContainer, ); }

回到前面demo-general專案中中初始化部分

//index.tx
(async function main() {
  await registerPlugins();

  init(document.getElementById('lce-container')!, {
    locale: 'zh-CN',
    enableCondition: true,
    enableCanvasLock: true,
    // 預設繫結變數
    supportVariableGlobally: true,
    requestHandlersMap: {
      fetch: createFetchHandler(),
    },
    appHelper,
  });
})();

3.解釋init()

export async function init(
  container?: HTMLElement, // 初始化函式引數:容器元素,可選
  options?: IPublicTypeEngineOptions, // 初始化函式引數:引擎選項,可選
  pluginPreference?: PluginPreference, // 初始化函式引數:外掛偏好設定,可選
) {
  await destroy(); // 銷燬之前的狀態,確保初始化乾淨

  let engineOptions = null; // 初始化引擎選項變數

  if (isPlainObject(container)) { // 如果容器是一個普通物件
    engineOptions = container; // 將容器作為引擎選項
    engineContainer = document.createElement('div'); // 建立一個新的 div 元素作為引擎容器
    engineContainer.id = 'engine'; // 設定容器的 id 為 'engine'
    document.body.appendChild(engineContainer); // 將容器新增到 body 中
  } else {
    engineOptions = options; // 使用傳入的引擎選項
    engineContainer = container; // 使用傳入的容器
    if (!container) { // 如果容器不存在
      engineContainer = document.createElement('div'); // 建立一個新的 div 元素作為引擎容器
      engineContainer.id = 'engine'; // 設定容器的 id 為 'engine'
      document.body.appendChild(engineContainer); // 將容器新增到文件的 body 中
    }
  }

  engineConfig.setEngineOptions(engineOptions as any); // 設定引擎配置的選項

  const { Workbench } = common.skeletonCabin; // 從骨架中解構出 Workbench 元件

  if (options && options.enableWorkspaceMode) { // 如果啟用工作區模式
    const disposeFun = await pluginPromise; // 等待外掛 Promise 的解析
    disposeFun && disposeFun(); // 如果存在 disposeFun 函式,則執行

    render( // 渲染工作區工作臺元件
      createElement(WorkSpaceWorkbench, {
        workspace: innerWorkspace, // 傳入內部工作區
        className: 'engine-main', // 設定類名
        topAreaItemClassName: 'engine-actionitem', // 設定頂部區域項的類名
      }),
      engineContainer, // 渲染到引擎容器中
    );

    innerWorkspace.enableAutoOpenFirstWindow = engineConfig.get('enableAutoOpenFirstWindow', true); // 設定內部工作區自動開啟第一個視窗的屬性
    innerWorkspace.setActive(true); // 設定工作區為活動狀態
    innerWorkspace.initWindow(); // 初始化視窗
    innerHotkey.activate(false); // 啟用快捷鍵
    await innerWorkspace.plugins.init(pluginPreference); // 初始化工作區外掛
    return; // 返回
  }

  await plugins.init(pluginPreference as any); // 初始化外掛

  render( // 渲染工作臺元件
    createElement(Workbench, {
      skeleton: innerSkeleton, // 傳入內部骨架
      className: 'engine-main', // 設定類名
      topAreaItemClassName: 'engine-actionitem', // 設定頂部區域項的類名
    }),
    engineContainer, // 渲染到引擎容器中
  );
}

再來找

最後,來到workbench.tsx中

4.workbench.tsx

export class Workbench extends Component<{
  workspace: Workspace; // 工作空間物件
  config?: EditorConfig; // 編輯器配置(可選)
  components?: PluginClassSet; // 外掛類集合
  className?: string; // 類名
  topAreaItemClassName?: string; // 頂部區域項的類名
}, {
  workspaceEmptyComponent: any; // 工作空間為空時的元件
  theme?: string; // 主題
}> {
  constructor(props: any) {
    super(props);
    const { config, components, workspace } = this.props;
    const { skeleton } = workspace;
    skeleton.buildFromConfig(config, components); // 從配置和元件構建骨架
    engineConfig.onGot('theme', (theme) => {
      this.setState({
        theme,
      });
    });
    engineConfig.onGot('workspaceEmptyComponent', (workspaceEmptyComponent) => {
      this.setState({
        workspaceEmptyComponent,
      });
    });
    this.state = {
      workspaceEmptyComponent: engineConfig.get('workspaceEmptyComponent'), // 獲取工作空間為空時的元件
      theme: engineConfig.get('theme'), // 獲取主題
    };
  }

  render() {
    const { workspace, className, topAreaItemClassName } = this.props;
    const { skeleton } = workspace;
    const { workspaceEmptyComponent: WorkspaceEmptyComponent, theme } = this.state;

    return (
      <div className={classNames('lc-workspace-workbench', className, theme)}>
        <SkeletonContext.Provider value={skeleton}>
          <TopArea className="lc-workspace-top-area" area={skeleton.topArea} itemClassName={topAreaItemClassName} /> {/* 渲染頂部區域 */}
          <div className="lc-workspace-workbench-body">
            <LeftArea className="lc-workspace-left-area lc-left-area" area={skeleton.leftArea} /> {/* 渲染左側區域 */}
            <LeftFloatPane area={skeleton.leftFloatArea} /> {/* 渲染左側浮動區域 */}
            <LeftFixedPane area={skeleton.leftFixedArea} /> {/* 渲染左側固定區域 */}
            <div className="lc-workspace-workbench-center">
              <div className="lc-workspace-workbench-center-content">
                <SubTopArea area={skeleton.subTopArea} itemClassName={topAreaItemClassName} /> {/* 渲染中上區域 */}
                <div className="lc-workspace-workbench-window">
                  {
                    workspace.windows.map(d => (
                      <WindowView
                        active={d.id === workspace.window?.id} // 判斷視窗是否啟用
                        window={d}
                        key={d.id}
                      />
                    ))
                  }

                  {
                    !workspace.windows.length && WorkspaceEmptyComponent ? <WorkspaceEmptyComponent /> : null // 根據條件渲染工作空間為空時的元件
                  }
                </div>
              </div>
              <MainArea area={skeleton.mainArea} /> {/* 渲染主區域 */}
              <BottomArea area={skeleton.bottomArea} /> {/* 渲染底部區域 */}
            </div>
            {/* <RightArea area={skeleton.rightArea} /> */}
          </div>
          <TipContainer /> {/* 渲染提示容器 */}
        </SkeletonContext.Provider>
      </div>
    );
  }
}

5.main-area.tsx

export default class MainArea extends Component<{ area: Area<any, Panel | Widget> }> {
  render() {
    const { area } = this.props;
    return (
      <div className={classNames('lc-main-area engine-workspacepane')}>
        {area.container.items.map((item) => item.content)}
      </div>
    );
  }
}

以上程式碼,

將area.container.items陣列中每個元素的content屬性渲染到頁面上,展示在MainArea元件所代表的區域內。

至此,低開引擎的初始化完成

相關文章