我遇到'不透明的标记'作为在Angular 2中实现全局常量的解决方案,例如:Define global constants in Angular 2
尽管阅读docs,我似乎无法理解这一点。
使用OpaqueToken比使用字符串作为标记更可取 由使用相同的多个提供者引起的可能冲突 字符串作为两个不同的标记。
什么?什么是开始的Angular2令牌?所有我得到的谷歌都是JSON网络代币(他们在auth等中的角色等)的答案,据我所知,但显然没有任何关联。
什么是不透明令牌?它用于什么?
P.S。在用于提供常量的不透明标记上有更多docs。然而,他们并没有帮助我。
答案 0 :(得分:55)
更新Angular4
在Angular4中OpaqueToken
已弃用,将由InjectionToken
替换。
InjectionToken允许传递泛型类型参数。
export let APP_CONFIG = new InjectionToken<MyConfig>("app.config");
另见
<强>原始强>
什么?什么是开头的Angular2令牌?
什么是不透明令牌?它用于什么?
令牌是Angulars依赖注入提供者的关键。 提供者注册了一个密钥,由DI实例化的组件,指令和服务类注入了依赖项,这些依赖项由提供者密钥查找。
DI支持类型,字符串,OpaqueToken
和对象作为键。
export let APP_CONFIG = new OpaqueToken("app.config");
export let APP_CONFIG_2 = {};
providers: [
MyService, // type is key and value
{provide: MyService, useClass: MyFancyServiceImpl}, // type is key, `MyFancyServiceImpl` is the value (or rather the information how to create the value
{provide: 'myservice', useClass: MyService}, // key is a string
{provide: APP_CONFIG, useValue: {a: 'a', b: 'b'}} // key is an `OpaqueToken`
{provide: APP_CONFIG_2, useValue: {a: 'a', b: 'b'}} // key is an object
]
// one of these decorators needs to be added to make DI work
@Injectable()
@Component()
@Directive()
@Pipe()
class MyComponent {
// DI looks up a provider registered with the key `MyService`
constructor(private myService: MyService) {}
// Same as before but explicit
constructor(@Inject(MyService) private myService: MyService) {}
// DI looks up a provider registered with the key 'myService'
constructor(@Inject('myservice') private myService: MyService) {}
// DI looks up a provider registered with the `OpaqueKey` `APP_CONFIG`
constructor(@Inject(APP_CONFIG) private myConfig: any) {}
// DI looks up a provider registered with the object `APP_CONFIG_2`
constructor(@Inject(APP_CONFIG_2) private myConfig: any) {}
对象键(APP_CONFIG_2
)和OpaqueToken
(APP_CONFIG
)必须是完全相同的实例。具有相同内容的不同实例不起作用。这样可以很容易地查找声明键的位置以及提供者和注入目标是否使用相同的键。
对于一个字符串,它可以是一个不同的实例,这会带来风险,即在不同的模块中使用相同的字符串值,并可能导致冲突或注入错误的提供者。
答案 1 :(得分:5)
什么是不透明令牌?它用于什么?
用于注入具有相同名称的另一个提供者(服务)的不透明令牌。
这可以避免命名冲突。
const MY_HTTP_TOKEN: OpaqueToken = new OpaqueToken('Http');
providers: [
{ provide: MY_HTTP_TOKEN, useClass: Http }
]
constructor(@Inject(MY_HTTP_TOKEN) private myHttpService){}
&#13;
答案 2 :(得分:3)
Opaque Token只是一个运行时类,用作注入提供程序的唯一标识符。
让我们说你有价值,&#39; secretId&#39;您想要用于一些服务和组件。您不希望在服务和组件中对此进行硬编码,因为它将来会发生变化。您还想为您的服务和组件编写测试。
使用类,您可以将该类用作实现,类型和注入器标记。对于字符串值,其他文字表达式,对象等 - 您没有任何东西可用作注入器令牌。您可以使用字符串作为注入器令牌,但不会发现该字符串将是唯一的。使用不透明令牌,即使两个令牌具有相同的名称,它们也将被评估为不同的令牌。
答案 3 :(得分:2)
我是angular 2的新手,但我想尝试在一个简单的代码中解释我对https://blog.thoughtram.io/angular/2016/05/23/opaque-tokens-in-angular-2.html的理解。 CMIIW。
...
const CONFIG_ONE = {title: 'My awesome app'};
let configOneToken = 'config'; //'config' is an example of string-type token
const CONFIG_TWO = {title: 'My fantastic app'};
let configTwoToken = 'config';
providers = [
{ provide: configOneToken, useValue: CONFIG_ONE },
{ provide: configTwoToken, useValue: CONFIG_TWO }
];
这段代码会有问题(后者会覆盖前者),因为它有冲突('config' == 'config'
)。
在玩具代码中它可能过于明显且毫无意义,但在实际代码中,当在第三方库中定义提供者之一时,我们可能无法轻易识别此冲突。
因此,为了解决这个问题,我们可以使用OpaqueToken,如下面的代码所示。
...
const CONFIG_ONE = {title: 'My awesome app'};
const OPAQUE_TOKEN_ONE = new OpaqueToken('config'); //this is an example of object-type token
const CONFIG_TWO = {title: 'My fantastic app'};
const OPAQUE_TOKEN_TWO = new OpaqueToken('config');
providers = [
{ provide: OPAQUE_TOKEN_ONE, useValue: CONFIG_ONE },
{ provide: OPAQUE_TOKEN_TWO, useValue: CONFIG_TWO }
];
任何相同类的两个实例永远不会相等(new OpaqueToken('config') != new OpaqueToken('config')
),因此避免冲突。 OpaqueToken
本身就是一个简单的无所事事的课程。