[英]emberjs glimmer object set() with variable property name
我在 Ember 3.15 中有一个组件,我正在尝试做类似的事情
import { action, set } from '@ember/object';
@action
someMethod() {
const value = ... // something random
let propertyName = ... // some variable string
set(this, propertyName, value);
}
它似乎在浏览器中运行良好,但 typescript 将设置行标记为错误(特别是 propertyName 参数)。 那么如果有效,为什么 typescript 不喜欢呢?
这似乎也发生在 get() 中,它不喜欢像get(this, propertyName)
这样的变量 propertyNames 。
一般来说,如果你的属性是@tracked
,你不需要set
,只需这样做this[propertyName] = value;
.
但是,您的问题可能是一般的 typescript 限制。 static打字的一个普遍问题:
Typescript 只做 static 分析。 所以它不会执行你的代码。 所以它无法知道动态生成的属性键是否真的存在。
所以如果你有这样的事情:
class Foo {
data1: number = 1;
data2: number = 2;
foo() {
const fixedProp = 'data1';
console.log(this[fixedProp]);
const dynamicProp = 'data' + (1 + 1);
console.log(this[dynamicProp]);
}
}
然后 typescript 将无法验证this[dynamicProp]
是否确实存在,因为为此它需要执行'data' + (1 + 1);
所以它会知道dynamicProp
实际上是什么。 所以通过 static 分析无法知道this[dynamicProp]
是否存在。
您可以通过(this as any)[dynamicProp]
告诉 typescript 做您想做的事情,它会忽略它。 但通常,如果您动态计算属性键,则不能依赖 static 分析。
您所描述的情况有两个基本问题 - 其中一个与 TypeScript 有关,其中一个与此无关。
TypeScript 的问题是 TS 通常知道属性的名称,并且会检查您是否正确设置了内容——无论是在使用普通 JS 属性查找和赋值时,还是在使用 Ember 的get
和set
函数时。 具体来说,Ember 的类型试图确保您在执行get
和set
时不会打错字。 您可以在此示例中看到为什么它们不允许任意字符串:
import Component from '@ember/component';
import { action, set } from '@ember/object';
export default class Whoops extends Component {
greeting = 'Hello';
@action updateGreeting(newGreeting) {
set(this, 'greering', newGreeting);
// ----^--- TYPO!!!
}
}
如果set
(或get
)的类型只允许任意字符串,那么 TS 在这里根本帮不了你; 它会让它成为 go,而且您必须自己找出错误 - 而不是编译器会帮助您提前告诉您。
在您遇到的情况下, TypeScript 可能只是看到一个字符串,它说“我没有任何方法可以检查这个字符串是否属于该属性。”
这里有几种改进方法。 首先,如果可以,您应该弄清楚是否可以将propertyName
的类型限制为它来自的类型的keyof
。 (解释keyof
超出了这个答案的 scope , 手册中的这一部分和这篇博文将让你快速上手。)
其次,与更大的问题有关:您在讨论该问题的另一个答案时指出,问题是您正试图在单个跟踪根 state 上深入设置属性。 通常,您不应该以这种方式改变自动跟踪的 state - 这是 Ember Classic 使用其计算属性的旧观察者驱动模式的保留。 相反,更愿意通过 state 的所有者来驱动对自动跟踪的 state 的所有更改。 那么你根本不需要set
,系统会自动正确更新。
您可以通过为嵌套 state本身自动跟踪来做到这一点,方法是为其定义一个 class 或使用类似跟踪内置插件的东西来包装一个普通的 JS ZA8CFDE6331BD59EB2AC96F8911C4B666 无论哪种方式,与其从任何地方深入并深入变异 state,不如仅在拥有该 state 的 object 上执行此操作。 如果您遵循该模式,并将propertyName
限制为keyof TheOwnerOfTheState
的键,其中TheOwnerOfTheState
是某个 class,那么在 Ember 端和 TypeScript 端,一切都将“正常工作”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.