部件的基本原理
部件是所有 Dojo 应用程序的基本构建要素。部件是主要的封装单元,它能表示从用户界面的单个元素,到更高级别的容器元素(如 Form 表单、段落、页面甚至是完整的应用程序)等所有内容。
前言: 降低复杂度
单个部件通常表示应用程序中的单个职责。细微的职责自然会转化为单独的部件,而复杂的职责就需要拆分为几个相互依赖的部分。然后,每部分就可以实现为一个部件,其中一个或多个父容器部件会协调所有拆开部件的交互。在这种层级结构中,可以看出根部件在整体上实现了更大的责任,但实际上它是通过组合很多简单的部件实现的。
对一个完整的应用程序的来讲,它的所有需求集就是一个单一的、复杂的责任。使用 Dojo 实现这个完整的需求集,会产生具有层级结构的部件,通常从根节点的“Application”部件开始,然后根据每层功能分支出层层部件,最终到达表示 HTML 页面中单个元素的叶节点。
简单的好处
让部件尽可能简单的原因有:对单个部件而言,降低复杂度意味着更大的职责隔离(缩小范围);更容易做全面测试;减少出错的机会;更有针对性的修复错误;以及更广泛的组件复用潜力。
从整个应用程序的层面看,简单的部件使得我们更容易理解每个组件,以及它们是如何组合在一起的。
这些好处会简化日常维护,并最终降低了构建和运行应用程序的总开销。
基本的部件结构
部件的核心只是一个渲染函数,该函数返回虚拟 DOM 节点,正是通过虚拟 DOM 节点描述部件在网页中的结构。但是,应用程序通常需要处理更多逻辑,不仅仅是简单的罗列 HTML 元素,因此有意义的部件通常不仅仅由简单的渲染函数组成。
部件通常位于它们各自的、单独命名的 TypeScript 模块中,且每个模块默认导出定义的部件。
表示部件最简单的方法是基于普通函数,从渲染函数的工厂定义开始。Dojo 的 @dojo/framework/core/vdom
模块中提供了一个 create()
函数,允许作者定义他们自己的部件渲染函数工厂。可优先使用命名的渲染函数,因为这样有助于调试;但并非必须如此;部件也可以使用一个被导出的变量标识,该变量保存了部件的工厂定义。
对于更喜欢使用类的结构而不是函数的应用程序,Dojo 也提供了基于类的部件。此部件继承 @dojo/framework/core/WidgetBase
模块中提供的 WidgetBase
,并必须要实现一个 render()
方法。
以下示例展示了一个 Dojo 应用程序的部件,虽然没有实际用途,但功能完整:
src/widgets/MyWidget.ts
基于函数的 Dojo 部件:
import { create } from '@dojo/framework/core/vdom';
const factory = create();
export default factory(function MyWidget() {
return [];
});
基于类的 Dojo 部件:
import WidgetBase from '@dojo/framework/core/WidgetBase';
export default class MyWidget extends WidgetBase {
protected render() {
return [];
}
}
因为此部件的渲染函数返回的是空数组,所以在应用程序的输出中没有任何内容。部件通常返回一到多个虚拟 DOM 节点,以便在应用程序的 HTML 输出中包含有意义的结构。
将虚拟 DOM 节点转换为网页中的输出是由 Dojo 的渲染系统处理的。
部件样式
部件的 DOM 输出的样式是由 CSS 处理的,相关的样式类存在 CSS 模块文件中,它与部件的 TypeScript 模块是对应的。基于函数的部件和基于类的部件使用相同的样式。该主题会在样式和主题参考指南中详细介绍。