如何将ES模块导入UI5控制器

How to import ES Module into UI5 controller

给定一个 ES 模块 dictionaryAPI.mjs:

export const DICTIONARY_API = Object.freeze({
    someKey: "someValue"
});

我想将它导入我的 UI5 控制器。据我了解,UI5 不支持 .mjs 扩展名,因此我将扩展名从 .mjs 更改为 .js。然后,我尝试将它添加到 UI5 控制器中,准确地说,是实用程序控制器 ControllerUtilities.js:

sap.ui.define([
    "com/myApp/dictionaryAPI"
    ],
    (dictionaryAPI) => ({…}));

当我 运行 应用程序时,出现错误:

'com/myApp/controller/ControllerUtilities.js': Unexpected token 'export'

sap-ui-core.js:53 Uncaught (in promise) ModuleError: Failed to resolve dependencies of 'com/myApp/controller/Login.controller.js'
 -> 'com/myApp/controller/BaseController.js'
  -> 'com/myApp/controller/ControllerUtilities.js': Unexpected token 'export'
    at p1 (https://openui5nightly.hana.ondemand.com/resources/sap-ui-core.js:53:213)
    at j1.failWith (https://openui5nightly.hana.ondemand.com/resources/sap-ui-core.js:40:43)
    at https://openui5nightly.hana.ondemand.com/resources/sap-ui-core.js:65:1556
Caused by: SyntaxError: Unexpected token 'export'

看来,UI5 无法识别来自 ES 模块的 export statemen。

是否有将 ES 模块导入 UI5 控制器的选项?

使用版本:OpenUI5 1.96.0

UI5 默认使用 UMD 导入语法 (sap.ui.define, sap.ui.require)。要使其理解其他模块类型,您必须 'trick' 认为该模块是 UMD。

这可以通过使用 ui5 cli 来完成。

你必须建立一个合适的文件夹结构(package.json、ui5.yaml、webapp文件夹)并且在ui5.yaml文件中你可以为相应的ES定义project shims模块。

一个便宜又笨拙的替代方案是通过 ES 模块包含 <script src="path/to/module" type="module"> 个标签,但我不知道有谁会推荐这个,因为它不允许捆绑。

最好的解决方案是创建一个新模块,如 fmi21 所述。

您的 API 可能看起来像这样,它只返回一个带有 DICTIONARY_API 的对象。因此,您还可以向 API.

添加更多属性
sap.ui.define([], function () {
"use strict";

    return {
        DICTIONARY_API : Object.freeze({
            someKey: "someValue"
        })
    }
});

然后您可以像在 ControllerUtilities.js

中一样导入它

您还可以通过 manifest.json

将 JSON 文件直接加载到模型中
{
  "sap.ui5": {
    "models": {
      "YOURMODELNAME": {
        "type": "sap.ui.model.json.JSONModel",
        "uri": "PATH TO JSON"
      }
    }
  }
}

如果它是一个模型,需要在系统范围内访问,最简单的方法是在 sap.ui5/models 下的 manifest.json 中声明它:

"dictionaryAPI": {
    "type": "sap.ui.model.json.JSONModel",
    "uri": "model/dictionaries/api.json"
},

或者,可以从根视图的控制器加载模型(rootView in manifest.json),这使得模型在整个应用程序期间可用于每个视图 运行:

async loadDictionaryData(dataSource, modelName) {

    const dictionaryModel = new JSONModel();

    await dictionaryModel.loadData(dataSource);

    this.getView().setModel(dictionaryModel, modelName);

}

无需关心数据sync/async加载、重用、ESM/UMD等