微件开发
微件是可复用的用户界面组件,是提供丰富用户体验的关键。GeoScene API for JavaScript 提供了一组即用型微件,为您创建自定义微件奠定了基础。
本指南主题讨论微件开发的基本原理。无论微件的预期功能如何,创建自定义微件的基础是一致的。其他信息部分提供了可帮助您入门的额外资源。
开发要求
在创建自己的自定义微件之前,您需要确保具备所需的要求。这些将根据您的微件要求而有所不同。下面列出的是微件开发的最低要求。
TypeScript
TypeScript 是 JavaScript 的超集。编写完成后,它可以编译成普通的 JavaScript。建议通过 TypeScript 进行微件发开。此处有一个出色的 TypeScript 设置指南页面,其中提供了一些使用 GeoScene API for JavaScript 设置 TypeScript 开发环境的基本步骤。还有大量的优秀在线资源,详细介绍了 TypeScript 是什么,为什么使用它,以及如何使用它。熟悉这些基础知识将使微件开发过程变得更加容易。
JSX
JSX 是一种 JavaScript 扩展语法,其允许以类似于 HTML 的方式描述微件 UI。它看起来类似于 HTML,因为它可以与 JavaScript 内联使用。
熟悉 geoscene/core/Accessor
Accessor 是 API 的核心功能之一,也是所有类(包括微件)的基础。有关其工作原理及其使用模式的其他详细信息,请参阅实现 Accessor主题。
微件生命周期
在开始开发之前,对微件生命周期有一个大致的了解非常重要。无论微件的类型如何,特定于其生命周期的一般概念是相同的。这些是:
- constructor (params) - 在设置任何所需属性时,这是最初创建微件的地方。由于微件派生自 Accessor,因此您可以访问获取、设置和监视属性,如使用属性主题中所述。
- postInitialize() - 此方法在创建微件之后,但在渲染 UI 之前调用。
- render() - 这是唯一必需的方法,用于渲染 UI。
- destroy() - 释放微件实例的方法。
TypeScript 装饰器
微件开发可利用 TypeScript 装饰器。这允许我们在设计时定义和修改现有属性、方法和构造函数中的常见行为。我们将在下面讨论最常见的微件装饰器类型。
@subclass
这些装饰器可被认为是用于创建API类的底层黏合剂。
以下代码段导入并扩展了基本 Widget
类,并在渲染方法中定义了 UI。JSX 用于定义 UI。在此简单方案中,将创建一个以 John Smith
为其内容的 div
元素。
@property()
此装饰器用于定义 Accessor 属性。现在可以 get
和 set
使用此装饰器定义的任何属性。此外,您还可以 watch
任何属性更改。
@aliasOf()
此装饰器允许定义属性别名。这有助于保持代码整洁,以免重复现有属性(例如,已在 ViewModel
中实现)。上面提供的完整示例不使用此装饰器。如果存在与此文件关联的 HelloWorldViewModel
,则可以通过此方法直接访问其属性,从而避免代码重复。
微件实现
以下步骤提供了实现您自定义微件时所需步骤的高度概述:
扩展微件
在最基本的级别上,您将首先通过从基本 Widget 类扩展来创建一个微件。
实现属性和方法
接下来,您可以实现特定于该微件的任何属性和/或方法。此代码片段演示了如何利用这些属性的装饰器。
默认情况下,元素中引用的函数将 this
设置为实际元素。您可以选择性地使用 bind 属性来更新 this
。下面绑定了 _onNameUpdate
回调方法,以便在监听 name
属性更新时使用。这显示在以下 postInitialize 方法中。
当微件属性准备就绪时,可在渲染之前调用 postInitialize 方法。在以下代码片段中,我们正在监视 name
属性。更新后,它将调用 _onNameUpdate
回调方法。watchUtils.init() 调用将返回一个 WatchHandle 对象,然后将其传递到 own() 中。这有助于在微件被破坏后清理所有资源。
渲染微件
实现属性后,使用 JSX 渲染微件的 UI。这在微件的渲染方法中处理,这是微件实现所需的唯一必需方法。
请注意,尚不支持作为 JSX 元素创建的微件。例如,以下代码段将不起作用。
const search = <Search view={view} />;
最后,在微件上调用 destroy 将处理微件并释放使用下面的 postInitialize 中引用的 own()
方法注册的所有资源。
导出模块
在代码页的最末尾,添加一行以导出对象。
微件渲染
下面列出的属性可用于渲染微件:
- classes:用于构建微件的类属性的值。这有助于简化 CSS 类设置。
- styles:允许动态更改样式。
- afterCreate:此回调方法在将节点添加到 DOM 后执行。任何子节点和属性都已应用。在渲染器中使用此方法访问真实 DOM 节点。也可使用每个元素。
- afterUpdate:每次更新节点时,都会执行此回调方法。
- bind:此属性用于为事件处理程序设置
this
的值。 - key:这用于唯一标识在其同级中的 DOM 节点。如果同级元素具有相同选择器,并且这些元素是动态添加/删除的,这一点很重要。
除了上面提到的方法,还有一个便利的 storeNode 方法。您可以使用它来分配引用变量的 HTMLElement DOM 节点。这将使用自定义数据属性 data-node-ref
来存储对元素 DOM 节点的引用。为使其正常工作,还必须将其绑定到微件实例,例如 bind={this}
,如以下代码片段所示。
ViewModel 模式
使用微件框架有两个部分。即:1)微件,以及 2)微件的 ViewModel。微件(即视图)部分负责处理微件的用户界面(UI),这意味着微件如何通过 DOM 显示和处理用户交互。ViewModel 部分负责微件的基础功能,或者更确切地说,负责其业务逻辑。
为什么要将微件框架分为这两个独立的部分?其中一个原因是,通过将微件的视图与其 ViewModel 分离,我们可以提高其可重用性的效率。通过关注微件的 ViewModel,您可以移除 UI 部分,并可专注于其核心逻辑。此逻辑可以重用,并通过具有不同 UI 实现的各种微件进行扩展。此外,从测试中移除 DOM/UI 也可加快速度,因为等式中少了一个因素。此外,由于 ViewModels 是从 geoscene/core/Accessor 扩展而来的,因此它们利用了 Accessor 的所有功能。这有助于保持 JavaScript API 各部分之间的一致性,因为许多其他模块也从此类派生而来。ViewModel 公开了支持视图所需功能所需的 API 属性和方法,而视图包含 DOM 逻辑。
那么这两个部分是如何协同工作的呢?当微件渲染时,将渲染其 state
。此状态派生自视图和 ViewModel 的属性。在微件生命周期的某个时刻,视图会调用 ViewModel 的方法/属性。反过来,这会导致属性或结果的更改。触发更改后,视图将收到通知,并将在 UI 端进行更新。
使用搜索微件和 SearchViewModel 的示例:
其他信息
有关详细信息,请参阅以下附加链接: