javascript - 嵌套的 JS 装饰器获取/设置,如何正确链接它们?
问题描述
该ember
框架积极地采用了装饰器。现在为了使用数据绑定,我必须装饰我的属性,@tracked
每当我更改属性时,我都会使用它来更新我所有漂亮的 UI。
@tracked username = 'dave';
这很好用,但是如果我需要在跟踪的装饰器之上添加自定义装饰器,我会遇到一些严重的问题。
@typed(StateTrackMap)
@tracked
mapConfigsArray = [create(StateTrackMap)];
通过让我的@typed
装饰器检查它是否在另一个装饰器之上,我可以让它工作。
export default function typed(classType) {
let weak = new WeakMap();
return function(object, property, descriptor) {
return {
get() {
// Check if there is another decorator attached below us in the chain
// i.e. "tracked"
if (typeof descriptor.get == 'function') {
return descriptor.get.call(this);
}
// If we haven't initialized before but there is one ready, return that
if (!weak.has(this) && typeof descriptor.initializer == 'function') {
weak.set(this, descriptor.initializer.call(this));
}
return weak.get(this);
},
set(value) {
// my set code which does the type checking/converting this descriptor is for
// Apply the converted value to the lower level object
// This may be the object itself, or it may be another setter in the chain
if (typeof descriptor.set == 'function') {
descriptor.set.call(this, typedValue);
} else {
return weak.set(this, typedValue);
}
}
}
}
}
但这感觉很奇怪……而且看起来不像我见过的描述符的任何用法。主要是因为如果我改变装饰器的顺序,事情就会爆炸
@tracked
@typed(StateTrackMap)
mapConfigsArray = [create(StateTrackMap)];
index.js:172 Uncaught Error: Assertion Failed: The options object passed to tracked() may only contain a 'value' or 'initializer' property, not both.
所以我想我的问题是,链接具有get
&的装饰器的正确方法是什么set
?在我看来,装饰器的顺序决定了我是否可以上链/下链。在我看来,这种链接逻辑必须融入到每个装饰器中,否则它不起作用。有没有一些通用的方法可以将装饰器传递给其他装饰器?
我已经看到了一些示例,其中我返回了描述符引用,但这似乎对这里的问题没有帮助,因为我不太确定如何get/set
在不擦除属性属性链或进入同一条船上的情况下仍然可以注入我的如上所述,我的代码必须设计为专门与其他描述符一起使用。
export default function typed(classType) {
return function(object, property, descriptor) {
const set = descriptor.set;
const get = descriptor.get;
const weak = new WeakMap();
descriptor.get = function() {
if (typeof get == 'function') {
return get.call(this);
}
// If we haven't initialized before but there is one ready, return that
if (!weak.has(this) && typeof descriptor.initializer == 'function') {
weak.set(this, descriptor.initializer.call(this));
}
return weak.get(this);
}
descriptor.set = function(value) {
// My type checking / conversion code
// Apply the converted value to the lower level object
// This may be the object itself, or it may be another setter in the chain
if (typeof set == 'function') {
set.call(this, typedValue);
} else {
return weak.set(this, typedValue);
}
}
return descriptor;
}
}
顺便说一句,这种方法给出了不同的爆炸。
Assertion Failed: You attempted to use @tracked on mapConfigsArray, but that element is not a class field.
解决方案
推荐阅读
- swift - Auto-Size UITableViewCell 的内部 UITableView
- javascript - Vue数组,获取完整数组作品,数组中的特定项目未定义
- console - 从外部地址访问管理 Web 控制台
- powershell - 从 txt 文件中获取数据并将其导出为 CSV
- asp.net-core - 多个长时间运行的 IHostedSerivces 或 BackgroundService 实现
- ruby - 如何在中间人 ruby 应用程序中使用 cookie?
- reactjs - 一个
可能只有一个子元素。尝试了一切 - mysql - 从 MySQL 中提取所有 JSON 密钥
- swift - 从 CIImage 创建 UIImage 似乎总是失败
- android - Worker 下的多个 OneTimeWorkRequest 导致我的应用程序冻结