Property Decorator
背景
实现 Properties 和 Attributes 的映射是编写 Custom Elements 时的良好实践。
例如以下的 JS 代码:
div.id = "my-id";
div.hidden = true;
将反馈到 DOM 中:
<div id="my-id" hidden></div>
反之,使用以上 html 内容渲染的页面,在 js 中也能读取相关属性。
console.log(div.id); // "my-id"
console.log(div.hidden); // true
另一方面,将构件的各个配置项作为独立属性平铺,也是推荐的良好实践。但由于实现这些属性代码稍显麻烦和冗余,例如处理 Boolean 类型的属性时:
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of `disabled` as an attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
this.toggleDrawer();
}
另外,为了能同步向 React 组件传递数据,我们还需要实现 static get observedAttributes() 及 attributesChangedCallback() 等代码,而实现这些属性及生命周期的方法同时也使我们要编写额外的测试代码以覆盖它们。
我们曾经提供过一组 Decorators: decorateCmdbObject, decorateCmdbInstance,但是它们与属性名捆绑,并且依然依赖构件作者自行声明 observedAttributes。这使得它们可扩展性差、易用性低。
为此我们提供了一个新的 Decorator: @property() 和构件基类 UpdatingElement,目的是大大简化属性的声明及构件的实现。
示例
import { UpdatingElement, property } from "@next-core/brick-kit";
class YourBrick extends UpdatingElement {
@property()
name: string;
@property({
type: Boolean;
})
required: boolean;
protected _render(): void {
// Render use `this.name` and `this.required`.
}
}
更多实际示例请参考 forms.general-input 等的实现。
对于现有构件的改造步骤如下:
- 修改构件继承至
UpdatingElement。 - 将
_render方法域改为protected。 - 移除原有属性代码,使用
@property()代替。 - 移除原有的
static get observedAttributes()及attributesChangedCallback()(它们已在UpdatingElement基类中实现了)。 - 从 bricks/forms/.babelrc 拷贝一份
.babelrc文件到所需构件库(当前是必须的,这是为了兼容其它构件库仍在使用的老版 decorators)。
注意
新/老 Decorator 无法共存,如需在构件库中使用新的 Decorator,需要将老的更换为新的
@property()。老 Decorator 也即将废弃,请尽快迁移。
配置说明
@property() 接收的参数如下:
| 名称 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| attribute | boolean 或 string | - | true | Property 映射的 attribute 名,默认将使用 property 转换为 kebab-case 后的字符串。 为 false 时表示不映射,复合值类型(如字典、数组等)不应映射 |
| type | String 或 Number 或 boolean | - | String | 属性类型,复合类型时留空,设置 attribute: false 即可。 |