uno*_*aii 6 forward-reference angular
What does forwardRef do in angular, and what is its usage?
here is an example:
import {Component, Injectable, forwardRef} from '@angular/core';
export class ClassCL { value; }
@Component({
selector: 'my-app',
template: '<h1>{{ text }}</h1>',
providers: [{provide: ClassCL, useClass: forwardRef(() => ForwardRefS)}]
})
export class AppComponent {
text;
constructor( myClass: ClassCL ) {
this.text = myClass.value;
}
}
Injectable()
export class ForwardRefS { value = 'forwardRef works!' }
Run Code Online (Sandbox Code Playgroud)
根据Angular的文档:
允许引用尚未定义的引用。
我认为,为了更好地了解forwardRef的工作原理,我们需要了解Javascript背后的情况。我将提供一个特定情况的示例,您可能需要使用forwardRef,但要考虑到可能会出现其他情况。
众所周知,Javascript函数位于其执行上下文的顶部。函数是对象本身,其他对象也可以从函数创建。由于函数允许程序员创建对象实例,因此ECMAScript 2015创建了某种语法糖,以使Javascript更加接近基于类的语言(如Java)。输入课程:
class SomeClassName { }
Run Code Online (Sandbox Code Playgroud)
如果我们进入Javascript编译器(在我的情况下,我使用的是Babel)并将其粘贴,结果将是:
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var SomeClassName = function SomeClassName() {
_classCallCheck(this, SomeClassName);
};
Run Code Online (Sandbox Code Playgroud)
最有趣的部分是注意到我们的类实际上是在后台运行的函数。像函数一样,变量也悬挂在其执行上下文中。唯一的区别是,尽管我们可以调用函数(因为即使悬挂了指针也可以引用它的指针),但变量仍被悬挂并赋予默认值undefined。在运行时,在赋值的给定行中,为变量分配了一个值,可能不是未定义的值。例如:
console.log(name);
var name = 'John Snow';
Run Code Online (Sandbox Code Playgroud)
实际上变成:
var name = undefined;
console.log(name) // which prints undefined
name = 'John Snow';
Run Code Online (Sandbox Code Playgroud)
好了,考虑到所有这些,现在让我们进入Angular。假设我们的应用程序中包含以下代码:
import { Component, Inject, forwardRef, Injectable } from '@angular/core';
@Injectable()
export class Service1Service {
constructor(private service2Service: Service2Service) {
}
getSomeStringValue(): string {
return this.service2Service.getSomeStringValue();
}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private service1Service: Service1Service) {
console.log(this.service1Service.getSomeStringValue());
}
}
export class Service2Service {
getSomeStringValue(): string {
return 'Some string value.';
}
}
Run Code Online (Sandbox Code Playgroud)
当然,我们需要提供这些服务。让我们在AppModule中提供它们:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent, Service1Service, Service2Service } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [Service1Service, Service2Service],
bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
AppModule元数据中的重要一行是:
providers: [Service1Service, Service2Service]
Run Code Online (Sandbox Code Playgroud)
如果运行此代码,将出现以下错误:
嗯,很有趣...这是怎么回事?好吧,根据之前的解释,Service2Service在后台成为一个函数,但是此函数被分配给了一个变量。该变量已吊起,但其值未定义。由于所有这些,无法解析参数。
输入forwardRef
为了解决这个问题,我们有一个名为forwardRef的漂亮函数。该函数的作用是将函数作为参数(在示例中,我使用箭头函数显示)。该函数返回一个类。forwardRef等待直到声明了Service2Service,然后触发箭头函数被传递。这导致返回创建Service2Service实例所需的类。因此,您的app.component.ts代码如下所示:
import { Component, Inject, forwardRef, Injectable } from '@angular/core';
@Injectable()
export class Service1Service {
constructor(@Inject(forwardRef(() => Service2Service)) private service2Service) {
}
getSomeStringValue(): string {
return this.service2Service.getSomeStringValue();
}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private service1Service: Service1Service) {
console.log(this.service1Service.getSomeStringValue());
}
}
export class Service2Service {
getSomeStringValue(): string {
return 'Some string value.';
}
}
Run Code Online (Sandbox Code Playgroud)
总之,基于我提供的示例,forwardRef允许我们引用稍后在源代码中定义的类型,从而防止代码崩溃并在组织代码中的方式方面提供更大的灵活性。
我真的希望我的回答对您有帮助。:)
允许引用尚未定义的引用。
例如,
forwardRef
当声明需要为DI引用的令牌但尚未定义该令牌时使用。当我们尚未定义创建查询时使用的令牌时,也会使用它。
Angular In Depth有不错的文章 。
这是摘录:
为什么forwardRef起作用?
现在,您的脑海中可能浮现出一个问题
forwardRef
。实际上,这与JavaScript中的闭包如何工作有关。当您在闭包函数中捕获变量时,它将捕获变量引用,而不是变量值。这是一个小例子,以证明这一点:Run Code Online (Sandbox Code Playgroud)let a; function enclose() { console.log(a); } enclose(); // undefined a = 5; enclose(); // 5
您可以看到,尽管在创建函数时
a
未定义变量enclose
,但它捕获了变量引用。因此,稍后将变量更新为时,5
它将记录正确的值。并且
forwardRef
只是一个函数,它将类引用捕获到闭包中,并且在执行该函数之前定义了类。Angular编译器在运行时使用函数resolveForwardRef解开令牌或提供程序类型。
归档时间: |
|
查看次数: |
3215 次 |
最近记录: |