可重复使用的UI组件和数据绑定
这个系列的文章将涵盖可重用的UI组件API设计的各个方面。本系列文章将利用Web Components进行实施演示,但API设计的概念和方法适用于所有UI组件框架。
在这篇文章中,我们将深入探讨UI组件在传递数据或设置UI组件的状态时的API设计。首先,让我们看一下我们的例子中的警报组件:

我们的警报组件有几个不同的选项。例如,这个警报组件可以有任何数量的视觉状态和使警报框可以关闭的选项。
属性vs.属性
对于许多Web UI框架和Web组件来说,数据是通过HTML属性或JavaScript属性传递给通用/可重用的组件。根据所使用的UI环境/工具,这种细微的差别可以被抽象出来。然而,了解这些差异以及它们如何影响你的API决策是至关重要的。
对于Web组件来说,同时支持HTML属性和JavaScript属性来设置组件上的数据是非常理想的。许多Web组件创作工具(如lit)提供了一种简单的方法,使属性和属性保持同步,以获得最大的灵活性和对组件消费者的支持。
属性是直接在HTML中设置的。属性总是字符串值,因为它是从DOM中解析出来的。然而,其他的数据类型,比如数字,只要你的组件转换了所提供的类型,就可以被传递进去。
<ui-alert status="success">success</ui-alert>
const alert = document.querySelector('ui-alert');alert.status = 'warning';
属性是在JavaScript的DOM对象上设置的。许多UI框架默认设置属性,而不是属性,而且大多数提供了一个模板语法来明确选择你想如何设置组件的值。
<!-- angular -->
<ui-alert [status]="value">property</ui-alert>
<ui-alert status="success">attribute</ui-alert>
<!-- lit -->
<ui-alert .status="value">property</ui-alert>
<ui-alert status="success">attribute</ui-alert>
<!-- vue -->
<ui-alert :status="value">property</ui-alert>
<ui-alert status="success">attribute</ui-alert>
数据绑定类别
当定义你的组件的数据输入时,有三个主要的类别,它们属于:
- 类型
status: info | success | error | warning - 状态
expanded | disabled | selected | collapsed | hidden - 行为
closable | draggable | sortable
Types 通常指的是在一个组件上定义的可视化选项。一个典型的例子是状态。例如,我们的警报的状态定义了视觉外观和感觉。
State 状态比类型更进一步,描述了一个组件的当前状态,不仅改变了视觉方面,也改变了组件的初始行为。
Behavior 定义了在一个组件中启用行为特征的方法。例子 允许组件支持拖放功能。draggable
不可能的状态
在设计你的组件API时,避免 "不可能的状态 "可以帮助防止混乱和整个类别的意外行为或错误。让我们用我们的警报组件作为一个例子。
<ui-alert success></ui-alert>
我们可以支持通过我们的警报添加一个success 属性/property,从功能上来说,它可以很好地工作。然而,这引入了一个轻微的误用风险。
<ui-alert success warning></ui-alert>
对于我们的状态来说,使用布尔风格的属性/属性,我们有可能意外地设置多个只代表一种类型的值。因此,我们可以使用一个枚举风格的类型,而不是使用布尔选项。
<ui-alert status="success"></ui-alert>
<ui-alert status="warning"></ui-alert>
<ui-alert status="danger"></ui-alert>
const alert = document.querySelector('ui-alert');
alert.status = 'warning';
我们通过利用单一的status 属性/property来降低类型重叠的风险。
布尔属性和属性
对于可重复使用的UI组件来说,遵循目前HTML所遵循的默认行为是最佳的。这有助于保持组件的熟悉和易于使用。如果在组件的API中没有正确的操作,布尔属性可能会引起混淆。
<button dissabled>is dissabled</button>
<button hidden>is hidden</button>
<button>not hidden or disabled</button>
默认情况下*,大多数*HTML元素的布尔属性在应用时是真实的,在从元素中移除时才是虚假的。
<ui-alert closable></ui-alert>
const alert = document.querySelector('ui-alert');
alert.closable = true;
如果你想让一个特定的行为默认开启,并允许它被移除,那么就否定这个功能。然而,向属性传递一个false 字符串仍然使属性是真实的。
<ui-alert closable="false">this is still closable</ui-alert>
如果我们的警报是默认可关闭的,我们需要调整我们的API以遵循布尔属性的行为并否定默认。
<ui-alert not-closable>this alert cannot be closed</ui-alert>
原始类型
在DOM引用上设置属性时,所有的JavaScript数据类型都可以使用。然而,在通过HTML属性设置数据时,一切都被视为字符串。
const list = document.querySelector('ui-list');list.items = [1, 2, 3];
像布尔和数字这样的原始类型转换为字符串是比较常见和直接的。今天的HTML元素就是这样做的。
<input type="range" value="5" min="0" max="10" />
- attribute/properties。
string | number | boolean - 仅限属性。
object | array
你的UI组件可以从字符串转换复杂的类型,如数组和对象;但是,这非常有限,而且有风险,因为它们可以有递归引用或定义的方法不能被序列化/反序列化。在我们的下一篇后续文章中,我们将挖掘利用声明式内容投影,以高度可重用的方式呈现更复杂的数据集或列表。请看下面的演示