3.5.17.2. 通用 JavaScriptComponent

在线示例

JavaScriptComponent 是个简单的 UI 组件,通过它可以使用任何纯 JavaScript 组件,并且这个 JavaSctipt 组件不需要对应的 Vaadin 实现。因此,通过这个组件可以很容易地在基于 CUBA 的项目中集成任何纯 JavaScript 组件。

该组件可以在界面的 XML 描述中以声明的方式定义,因此可以在 XML 中配置动态属性和 JavaScript 依赖。

该组件的 XML 名称: jsComponent

定义依赖

可以为该组件定义一个依赖列表(JavaScript、CSS)。依赖可以从以下源获取:

  • WebJar 资源 - 以 webjar:// 开头。

  • VAADIN 目录下的文件 - 以 vaadin:// 开头。

  • Web 资源 - 以 http://https:// 开头。

如果依赖的类型不能从扩展中得知,需要在 XML 的 type 属性中指定类型或者传递 DependencyType 枚举值给 addDependency() 方法。

在 XML 中定义依赖的示例:

  1. <jsComponent ...>
  2. <dependencies>
  3. <dependency path="webjar://leaflet.js"/>
  4. <dependency path="http://code.jquery.com/jquery-3.4.1.min.js"/>
  5. <dependency path="http://api.map.baidu.com/getscript?v=2.0"
  6. type="JAVASCRIPT"/>
  7. </dependencies>
  8. </jsComponent>

以编程方式添加依赖的示例:

  1. jsComponent.addDependencies(
  2. "webjar://leaflet.js",
  3. "http://code.jquery.com/jquery-3.4.1.min.js"
  4. );
  5. jsComponent.addDependency(
  6. "http://api.map.baidu.com/getscript?v=2.0", DependencyType.JAVASCRIPT
  7. );

定义初始化函数

该组件需要一个初始化函数。此函数的名称用来查找 JavaScript 组件连接器(connector)的入口(见下例)。

初始化函数的名称在一个 WEB 浏览器窗口内必须唯一。

函数名称可以通过 setInitFunctionName() 方法传递给组件:

  1. jsComponent.setInitFunctionName("com_company_demo_web_screens_Sandbox");

定义 JavaScript 连接器(connector)

要使用 JavaScriptComponent 来包装 JavaScript 库,需要定义 JavaScript 连接器,其功能主要是初始化 JavaScript 组件并且处理服务端和 JavaScript 代码之间的通信。

连接器函数中可以使用下面的方法:

  • this.getElement() 返回组件的 HTML DOM 元素。

  • this.getState() 返回与服务端同步的带有当前状态的共享状态对象。

组件功能

JavaScriptComponent 组件有下列功能:

  • 设置一个状态对象,该对象可以在客户端层的 JavaScript 连接器中使用,并且可以通过组件状态的 data 字段访问,示例:

    1. MyState state = new MyState();
    2. state.minValue = 0;
    3. state.maxValue = 100;
    4. jsComponent.setState(state);
  • 注册一个函数,该函数可以在 JavaScript 中使用提供的名称进行调用,示例:

    1. jsComponent.addFunction("valueChanged", callbackEvent -> {
    2. JsonArray arguments = callbackEvent.getArguments();
    3. notifications.create()
    4. .withCaption(StringUtils.join(arguments, ", "))
    5. .show();
    6. });
    1. this.valueChanged(values);
  • 调用命名的函数,该函数由连接器的 JavaScript 代码添加到包装的对象中。

    1. jsComponent.callFunction("showNotification ");
    1. this.showNotification = function () {
    2. alert("TEST");
    3. };

JavaScriptComponent 使用示例

本节介绍如何在基于 CUBA 的应用中集成第三方 JavaScript 库,使用 https://quilljs.com/ 的 Quill 富文本编辑器作为例子。请按照下面的步骤集成。

  1. web 模块添加以下依赖:

    1. compile('org.webjars.npm:quill:1.3.6')
  2. 在 web 模块的 web/VAADIN/quill 目录内创建 quill-connector.js 文件。

  3. 在此文件内,添加连接器的实现:

    1. com_company_demo_web_screens_Sandbox = function () {
    2. var connector = this;
    3. var element = connector.getElement();
    4. element.innerHTML = "<div id=\"editor\">" +
    5. "<p>Hello World!</p>" +
    6. "<p>Some initial <strong>bold</strong> text</p>" +
    7. "<p><br></p>" +
    8. "</div>";
    9. connector.onStateChange = function () {
    10. var state = connector.getState();
    11. var data = state.data;
    12. var quill = new Quill('#editor', data.options);
    13. // Subscribe on textChange event
    14. quill.on('text-change', function (delta, oldDelta, source) {
    15. if (source === 'user') {
    16. connector.valueChanged(quill.getText(), quill.getContents());
    17. }
    18. });
    19. }
    20. };
  4. 创建一个界面,包含以下 jsComponent 定义:

    1. <jsComponent id="quill"
    2. initFunctionName="com_company_demo_web_screens_Sandbox"
    3. height="200px"
    4. width="400">
    5. <dependencies>
    6. <dependency path="webjar://quill:dist/quill.js"/>
    7. <dependency path="webjar://quill:dist/quill.snow.css"/>
    8. <dependency path="vaadin://quill/quill-connector.js"/>
    9. </dependencies>
    10. </jsComponent>
  5. 添加下面的界面控制器实现:

    1. @UiController("demo_Sandbox")
    2. @UiDescriptor("sandbox.xml")
    3. public class Sandbox extends Screen {
    4. @Inject
    5. private JavaScriptComponent quill;
    6. @Inject
    7. private Notifications notifications;
    8. @Subscribe
    9. protected void onInit(InitEvent event) {
    10. QuillState state = new QuillState();
    11. state.options = ParamsMap.of("theme", "snow",
    12. "placeholder", "Compose an epic...");
    13. quill.setState(state);
    14. quill.addFunction("valueChanged", javaScriptCallbackEvent -> {
    15. String value = javaScriptCallbackEvent.getArguments().getString(0);
    16. notifications.create()
    17. .withCaption(value)
    18. .withPosition(Notifications.Position.BOTTOM_RIGHT)
    19. .show();
    20. });
    21. }
    22. class QuillState {
    23. public Map<String, Object> options;
    24. }
    25. }

执行结果,界面中可以看到 Quill 富文本编辑器:

jsComponent example

另一个集成自定义 JavaScript 组件的例子可以参阅 使用 JavaScript 库