建议和反馈

请填写你的反馈内容

深入了解ANGLE 2架构和功能-2

2019-10-04 ·1280次阅读 ·读完需要24分钟

了解观点孩子和满足孩子

存在于组件标签内的元素称为内容子项,而存在于组件模板内的元素称为视图子项
要在组件的视图中显示组件的子内容,我们需要使用<ng-content>标记。让我们看一个例子。
将此代码放在App组件的代码上方:
var ListItem = ng.core.Component({选择器:“ item”,
输入:[“ title”],
模板:“ <li> {{title}} | <ng-content> </ ng-content> </ li>“,
})。Class({ 
构造函数:function(){} 
})

var List = ng.core.Component({选择器:“列表”,
模板:“ <ul> <ng-content select ='item'> </ ng-content> </ ul>” 
}}。Class({ 
构造函数:function(){} 
})
现在,将App组件的代码更改为此:
var App = ng.core.Component({选择器:“ app”,
指令:[Cards,SampleComponent1,List,ListItem],templateUrl:“ componentTemplates /app-template.html“ 
})。Class({ 
构造函数:function(){} 
})
在app-template.html文件的末尾,添加以下代码:
<br> 
<list> 
<item title =” first “>第一</ item> 
<item title =” second“>第二</ item> 
</ list> 
此代码的输出如下:
JS角网开发

这三个代码段是这样工作的:

  • 在App组件的模板文件中,我们添加一个<list>标记,该标记显示一个列表。在其开始和结束标记中,我们定义了应显示的各个列表项。

  • 我们创建绑定到<list>和的ListItem和List组件。

<item>标签。

  • 我们将List组件添加到App组件而不是List的指令属性中,因为<list>标记位于App组件的模板中,并且App组件负责创建其实例。

  • App组件在广告模板的模板中查找<ng-content>标签。

List组件并在那里呈现List组件实例。

  • <ng-content>具有一个可选的select属性,该属性分配给CSS选择器,该选择器指示我们要显示的内容子级的哪些元素。模板中可以有多个<ng-content>标签。如果未提供select属性,则将渲染所有内容子级。在这里,select属性不是必需的。我们仅将其用于演示。

获取内容子级组件的参考并查看子级

要访问对视图子级或内容子级的组件的引用,我们可以使用ng.core.ContentChildren,ng.coreViewChildren,ng.core.ContentChild和ng.core.ViewChild构造函数。ng.core.ContentChildren和ng.core.ContentChild之间的区别在于,第一个返回给定组件的所有引用,而第二个返回第一个引用的引用。ng.core.ViewChild和ng.core.ViewChildren也具有相同的区别。
这是一个演示ng.core.ContentChildren的示例。用以下代码替换List组件的代码:
var List = ng.core.Component({选择器:“列表”,
模板:“ <ul> <ng-content select ='item'> </ ng-content> </ ul>“,查询:{
list_items:新的ng.core.ContentChildren(ListItem)

})。Class({ 
构造函数:function(){},ngAfterContentInit:function(){ 
this.list_items._results.forEach(function(e){console.log(e .title); 
})

})
在控制台中此代码的输出如下:
第一,
第二,

大部分代码是不言自明的。新增功能是ngAfterContentInit生命周期方法。内容子级已初始化后触发。同样,如果要访问视图子级,则需要使用ngAfterViewInit生命周期方法。
请注意,我们只能访问组件的状态,而没有其他权限。


局部模板变量

我们可以将本地模板变量分配给内容子项或查看子项。局部模板变量使我们能够获取内容子级或视图子级的任何元素的引用,即组件引用或HTML元素引用。
要将局部模板变量分配给视图子级或内容子级的元素,我们需要在开始标记中放置#variable_name。
这是一个示例,演示本地模板变量如何工作。将此代码放在App组件上方:
var SampleComponent2 = ng.core.Component({选择器:“ sampletwo”,
模板:“ <input type ='text'#input />”,查询:{ 
input_element:new ng.core。 ViewChild(“ input”)

})。Class({
构造函数:function(){},ngAfterViewInit:function(){ 
this.input_element.nativeElement.value =“ Hi”; 

})
将App组件的代码更改为此:
var App = ng.core.Component({选择器:“ app”,
指令:[Cards,SampleComponent1,List,ListItem,SampleComponent2],
templateUrl:“ componentTemplates / app-template。 html“ 
})。Class({ 
构造函数:function(){} 
})
然后,将此代码添加到app-template.html文件的末尾:
<sampletwo> </ sampletwo>

此代码的输出如下:
JS角网开发

这三个代码段的工作方式如下:

  • 我们创建一个名为SampleComponent2的新组件,该组件显示一个HTML输入文本元素。我们将输入元素分配给名为input的本地模板变量。

  • 然后,我们使用ng.core.ViewChild获得对该元素的引用。如果我们将字符串传递给ng.core.ViewChild,ng.core.ViewChildren,ng.core。ContentChild和ng.core.ContentChildren,那么它们将查找与字符串具有相同局部变量名称的元素,并且如果我们传递组件,则它们将像之前看到的那样寻找该组件。

  • 从本地模板变量获取的组件的引用与我们之前获得的接口相同。但是对于HTML元素引用,我们可以使用nativeElement属性访问元素的实际DOM。

组件生命周期方法

当出现组件标签时,Angular 2会创建一个组件实例,进行渲染,检查属性更改,检查状态更改,并在不再需要时销毁它。这些步骤共同构成了组件的生命周期。
Angular 2使我们可以注册在组件生命周期各个阶段调用的方法。
这是Angular 2提供的各种生命周期方法。生命周期挂钩按它们发生的顺序进行了说明:

  • ngOnChanges:每当组件的属性更改时,将调用此方法。在创建组件的新实例之后,首次解析组件的属性后,也会调用该方法。在状态由于属性而改变之后但在视图更新之前被调用。此方法接收属性的当前值和先前值。

  • ngOnInit:在第一个ngOnChanges实例之后调用。它指出已成功创建该组件并已读取属性。

  • ngDoCheck:在每个更改检测周期内和ngOnInit之后立即调用此方法。我们可以检测到并根据Angular 2自身无法或无法检测到的更改采取行动。在Angular 2完成检查组件的状态更改后调用此方法,并且如果属性中有任何更改但在更新组件视图之前已更新状态。调用结束后,将渲染视图,并在渲染视图时显示ngAfterContentInit,ngAfterContentChecked,ngAfterViewInit和ngAfterViewChecked

被调用。

  • ngAfterContentInit:在初始化内容子级但尚未呈现之后,即在已调用内容子级的ngOnChanges,ngOnInit,ngDoCheck,ngAfterContentInit和ngAfterContentChecked方法之后,调用此方法。

  • ngAfterContentChecked:每当更改检测周期检查内容子项是否已更改以及紧接在ngAfterContentInit之后,都将调用此方法。如果有更改,则会在更新内容子视图之前调用它。在调用它之前,将更新ng.core.ViewChildren,ng.core.ContentChildren等的查询结果,即在调用内容子项的ngAfterContentChecked之后调用它。通话后,内容子视图

已更新。

  • ngAfterViewInit:在初始化视图子项但尚未呈现之后调用,即在调用视图子项的ngOnChanges,ngOnInit,ngDoCheck,ngAfterContentInit,ngAfterContentChecked,ngAfterViewInit和ngAfterViewChecked方法之后调用。

  • ngAfterViewChecked:每当更改检测周期检查视图子项是否已更改以及在ngAfterViewInit之后立即更改时,将调用此方法。如果有更改,则会在更新视图子视图之前但在调用视图子视图的ngAfterViewChecked方法之后调用它。

  • ngOnDestroy:在销毁组件之前调用它。组件的ngOnDestroy方法在其内容子级和查看子级的ngOnDestroy方法之前被调用。

编写模板

我们需要使用模板语言来编写组件模板。模板语言由HTML以及{},[],(),[()],*,|和#标记组成。让我们看看它们的用途以及如何使用它们。

 

呈现值

为了简单地呈现this关键字的属性,我们需要使用{{}}令牌。在这些花括号内,我们可以简单地放置属性名称。
我们只能将表达式放在花括号内。我们放置在其中的表达式看起来像JavaScript。但是,我们不允许在这些花括号内使用一些JavaScript表达式。他们来了:

  • 分配(=,+ =,-=)

  • 新的运营商

  • 用链接表达式; 要么 ,

  • 增量和减量运算符(++和-)

  • 按位运算符| 和&

管道

我们也可以将管道放在大括号中。管道是一个接受输入值并返回转换后值的函数。管道由|表示。操作员。大括号内表达式的最终结果可以使用管道进行转换。括号中的管道数量可以根据需要设置。管道也可以采用参数。
Angular 2提供了一些内置管道:日期,大写,小写,货币和百分比。我们也可以创建自己的管道。
这是使用{{}}的示例。将此代码放在App组件上方:
var SampleComponent3 = ng.core.Component({选择器:“ samplethree”,
模板:“ {{info.firstname + info.lastname |大写}}”“ 
}))。Class({ 
构造函数:function (){this.info = {
firstname:“ firstname”,lastname:“ lastname” 


})


用以下代码替换App组件代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3],
templateUrl:“ componentTemplates / app-template.html “ 
})。Class({ 
构造函数:function(){} 
}))
然后将其放在app-template.html文件中:
<br> <br> 
<samplethree> </ samplethree> 
代码的输出为如下:
JS角网开发

 

处理事件

要处理模板中元素的事件,我们需要使用()运算符。这是一个如何处理事件的示例。将此代码放在App组件代码上方:
var SampleComponent4 = ng.core.Component({选择器:“ samplefour”,
模板:“ <input(click)='clicked($ event)'(mouseover)='mouseover($ event )'type =' button'value 
='Click Me !!!'/>“ 
})。Class({ 
构造函数:function(){this.clicked = function(e){ 
alert(” Hi from SampleComponent4“); 
} ;

this.mouseover = function(e){console.log(“ Mouse over event”); 
}


})
用以下代码替换App组件代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4],templateUrl:“ componentTemplates / app-template.html“ 
})。Class({ 
构造函数:function(){} 
})
将此代码放在app-template.html中:
<br> <br> 
<samplefour> </ samplefour> 
前面的代码是自解释性的。

将状态绑定到元素属性

要将this关键字的属性值绑定到模板中元素的属性,我们可以像这样简单地使用{{}},例如:
<component title =“ {{title}}”> </ component> 
但如果要传递对象,则此方法将不起作用,因为{{}}令牌内的表达式始终会转换为字符串。因此,Angular 2提供了
[]运算符,该运算符使组件可以通过属性将对象传递给
模板中的组件。
这是一个示例来证明这一点。将此代码放在App组件代码上方:
var SampleComponent5 = ng.core.Component({选择器:“ samplefive”,
输入:[“ info”],
模板:“ {{info.name}}” 
}))。
构造函数:function(){} 
})

var SampleComponent6 = ng.core.Component({选择器:“ samplesix”,
指令:[SampleComponent5],
模板:“ <samplefive [info] ='myInfo'> </ samplefive>” 
})。Class({

构造函数:function(){this.myInfo = { 
名称:“ Name” 


})
用以下代码替换App组件的代码:
var App = ng.core.Component({选择器:“ app”,
指令:[Cards,SampleComponent1 ,列表,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6],
templateUrl:“ componentTemplates / app-template.html” 
})。Class({ 
构造函数:function(){} 
})
将此代码放在应用程序的末尾, template.html文件:
<br> <br> 
<samplesix> </ samplesix> 
此代码的输出如下:
JS角网开发

双向数据绑定

默认情况下,Angular 2不使用双向数据绑定。它使用单向绑定,但如果需要,可提供[()]运算符进行双向数据绑定。
这是一个演示[()]的示例。将此代码放在App 
组件的代码上方:
var SampleComponent7 = ng.core.Component({选择器:“ sampleseven”,
模板:“ <input [(ngModel)] ='name'/> <input(click)='clicked( )'value ='Click here'type ='submit'/>“” 
})。Class({ 
构造函数:function(){},单击:function(){ 
alert(this.name); 

})
替换App组件代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7],
templateUrl:“ componentTemplates / app-template.html” 
})。Class({ 
构造函数:function(){} 
})
放置app-template.html文件中的代码:
<br> <br> 
<sampleseven> </ sampleseven> 
此代码的输出如下:
JS角网开发

在这里,在文本字段中输入内容,然后单击按钮。您将看到一个带有文本字段值的警报框。 要捕获HTML表单元素的值,我们需要将ngModel放在[()]括号内。如果要在输入和输出之间建立双向数据绑定,则可以放置属性名称。稍后我们将详细了解输出。 

指令

指令用于根据状态更改DOM。指令有两种类型:属性指令和结构指令。让我们看看它们中的每一个。

属性指令

一个属性指令改变基于在状态变化的DOM元素的外观或行为。ngClass和ngStyle是内置的属性指令。
我们还可以创建自己的属性指令。
ngClass指令用于从元素中添加或删除CSS类,而ngStyle指令用于设置内联样式。
这是有关如何使用ngClass和ngStyle指令的示例。将此代码放在App组件的代码上方:
var SampleComponent8 = ng.core.Component({选择器:“ sampleeight”,
模板:“ <div [ngStyle] ='styles'[ngClass] ='classes'> </ div>” 
})。Class({ 
构造函数:function(){this.styles = { 

}

this.classes = {a:true,
b:true,c:false 
}; 

}

用以下代码替换App组件的代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8],templateUrl: “” componentTemplates / app-template.html“ 
})。Class({ 
构造函数:function(){} 
})
然后,将此代码放在app-template.html文件的末尾:
<sampleeight> </ sampleeight> 
现在,如果您在浏览器开发人员工具中检查<sampleeight>标记,则会看到以下内容:
JS角网开发

大部分代码是不言自明的。您可以看到相同的[]标记也用于属性指令。使用[]标记时,Angular 2首先检查是否存在带有该名称的内置属性指令或自定义指令,如果没有,则将其视为属性。

结构指令

结构指令通过添加或移除DOM元素改变DOM布局。ngIf,ngSwitch和ngFor是三个内置的结构指令。我们还可以创建自己的自定义结构指令。
这是一个演示ngIf和ngSwitch的示例。之前我们已经看过ngFor的示例。将此代码放在App组件的代码上方:
var SampleComponent9 = ng.core.Component({选择器:“ samplenine”,
templateUrl:“ componentTemplates / samplecomponent9-template.html” 
})。Class({ 
构造函数:function(){

this.display1 = true; this.display2 = false; this.switchOption ='A'; 

})
创建一个名为samplecomponent9-template.html文件,并将其放置在
componentTemplates目录。将此代码放在该文件中:
<br> <br>

<div * ngIf =“ display1”>你好</ div> 
<div * ngIf =“ display2”>你好</ div>

<span [ngSwitch] =“ switchOption”> 
<span * ngSwitchWhen =“'A'”> A </ span> 
<span * ngSwitchWhen =“'B'”> B </ span> 
<span * ngSwitchWhen =“'C '“> C </ span> 
<span * ngSwitchWhen =”'D'“> D </ span> 
<span * ngSwitchDefault> other </ span> 
</ span> 
用以下代码替换App组件的代码:
var App = ng .core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8,SampleComponent9],
templateUrl:“ componentTemplates / app-template。html“ 
})。Class({ 
构造函数:function(){} 
})
最后,将此代码放在app-template.html文件中:
<samplenine> </ samplenine> 
此代码的输出如下:
JS角网开发

 

大部分代码是不言自明的。您可以看到我们在结构指令中使用了*标记。*标记将元素视为模板,即,它不呈现元素,而是将其用作创建DOM的模板。
实际上,属性和结构指令都是使用[]标记编写的,但是使用结构指令和[]标记编写的代码会使代码更长。
因此,Angular 2引入了*令牌,这使得使用结构化指令编写代码变得容易。在内部,Angular 2将使用*标记的代码转换为使用[]标记。在此处了解更多信息:
https : //angular.io/docs/ts/latest/guide/template-syntax.html#!#star- template

输出

输出允许组件发出自定义事件。例如,如果我们有一个显示按钮的组件,并且希望父组件能够为子组件的click事件添加事件处理程序,则可以使用输出来实现。
这是如何集成输出的示例。将此代码放在App 
组件的代码上方:
var SampleComponent10 = ng.core.Component({选择器:“ sampleten”,
输出:[“ click”],模板:“” 
}))。Class({ 
构造函数:function(){ 
this .click = new ng.core.EventEmitter(); setInterval(function(){ 
this.click.next({}); 
} .bind(this),10000)

})

var SampleComponent11 = ng.core.Component({选择器:“ sampleeleven”,
指令:[SampleComponent10],模板:“ <br> <sampleten 
(click)='clicked($ event)'> </ sampleten> {{value} }“ 
})。Class({ 
构造函数:function(){this.value = 1; 
this.clicked = function(e){this.value ++; 


})
用以下代码替换App组件的代码:
var App = ng。 core.Component({选择器:“ app”,
指令:[卡片,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8,SampleComponent9,SampleComponent11],
templateUrl:“ componentTemplates / app-template。html“ 
})。Class({
构造:函数(){} 
})
最后,把这个代码的应用程序,template.html文件的末尾:
<sampleeleven> </ sampleeleven> 
现在,你将开始看到一个计数器出现在页面上。
输出属性用于定义组件发出的事件。我们需要在此关键字中创建一个与输出名称相同的属性,并将其分配给ng.core.EventEmitter的新实例,以便它可以发出事件。ng.core。EventEmitter为对象提供观察者模式。
要捕获事件,我们需要使用()令牌,就像我们用来捕获本机UI事件一样。

具有输入和输出的双向数据绑定

您可以在输入和输出之间实现双向数据绑定。例如,如果父组件将属性传递给视图子组件,
并且只要输入值
发生变化,子组件就会通知父组件,那么我们可以使用[[]],而不是分别使用()和[]。
这是一个示例来证明这一点。将此代码放在App组件的代码上方:
var SampleComponent12 = ng.core.Component({选择器:“ sampletwelve”,
输入:[“ count”],输出:[“ countChange”],模板:“” 
})。Class( { 
构造函数:function(){ 
this.countChange = new ng.core.EventEmitter(); setInterval(function(){ 
this.count ++; this.countChange.next(this.count);
} .bind(this),10000); 

}                 

var SampleComponent13 = ng.core.Component({选择器:“ samplethirteen”,
指令:[SampleComponent12],模板:“ <br> <sampletwelve 
[(count)] ='count'> </ sampletwelve> {{count}}” 
})。Class({ 
构造函数:function(){this.count = 1; 

})
用以下代码替换App组件的代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡片, SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8,SampleComponent9,SampleComponent11,SampleComponent13],
templateUrl:“ componentTemplates / app-template.html” 
})。类({ 
构造函数:function(){} 
})

最后,将此代码添加到app-template.html文件的末尾:
<samplethirteen> </ samplethirteen> 
在这里,输出与前面的示例相同。大多数事情是不言自明的。您唯一需要知道的是这两个代码片段都具有相同的功能:
<sampletwelve [(count)] ='count'> </ sampletwelve> 
<sampletwelve [count] ='count'(countChange)='count = $ event'> </ sampletwelve>

了解提供者

一个供应商告诉角2如何同时注入它创建一个服务的实例。提供程序是使用组件的provider或viewProviders属性设置的。
让我们看一下如何创建提供程序的示例。将此代码放在App 
组件的代码上方:
var Service1 = ng.core.Class({构造函数:function(){ 
},
getValue:function(){return“ xyz” 

}));

var Service2 = ng.core.Class({构造函数:function(){ 
},
getValue:function(){return“ def” 

});

var Service3 = ng.core.Class({构造函数:function(){ 
},
getValue:function(){return“ mno” 

});

var Service4 = ng.core.Class({ 
构造函数:[Service2,Service3,function(s2,s3){console.log(s2); 
console.log(s3); 
}],
getValue:function(){返回“ abc “ 

});

var ServiceTest1 = ng.core.Component({选择器:“ st1”,
viewProviders:[ 
ng.core.provide(Service1,{useClass:Service4}),ng.core.provide(Service2,{useValue:“ def”}) ,ng.core.provide(Service3,{useFactory:function(){ 
return“ mno”; 
}})
]],
模板:“” 
})。Class({ 
构造函数:[Service1,function(s1){console.log( s1.getValue()); 
}] 
})
用以下代码替换App组件的代码:
var App = ng.core.Component({选择器:“ app”,
指令:[卡,SampleComponent1,列表,列表项,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8,SampleComponent9,SampleComponent11,SampleComponent13,
ServiceTest1],
templateUrl: “componentTemplates / APP-template.html” 
})类({ 
构造:function(){} 
})
最后,将其添加到app-template.html文件的末尾:
<st1> </ st1>

 

这是代码的控制台输出:
def mno abc
这是如何工作的:

  1. 首先,我们创建四个服务:Service1,Service2,Service3和Service4。它们都有一个getValue方法,该方法返回一个字符串。Service4依赖于Service2和Service3。

  2. 然后,我们创建一个名为ServiceTest1的组件。它取决于Service1。在viewProviders属性中,我们传递了一组提供程序。提供程序是使用ng.core.provide方法创建的。它有两个参数。第一个是服务名称,第二个是配置对象,它说明如何创建此服务的实例。当请求第一个参数中的服务实例时,useClass属性告诉Angular 2创建该服务实例。因此,在这里,当需要Service1的实例时,将实际创建Service4的实例。同样,useValue用于提供值,useFactory用于将控制权传递给函数,以决定在请求新实例时返回什么。所以在这里,当Service2的一个实例是

请求时,我们获得def字符串,而当请求Service3时,我们获得
mno字符串。
在本文前面,我们只是将viewProviders分配给服务本身。服务还实现提供程序的接口,以便它创建服务本身的实例。
如果有多个提供程序与服务匹配,则最新的提供程序将覆盖前一个。

提供者和viewProviders属性之间的区别

viewProviders属性使我们只能使提供程序可用于组件的视图,而providers属性可以使提供程序对其内容的子级和视图子级可用。
provider属性仅创建一次服务实例,然后将其提供给任何要求它的组件。我们已经看到了viewProviders是如何工作的。让我们看一个提供程序如何工作的示例。将此代码放在App组件的代码上方:
var counter = 1;

var Service5 = ng.core.Class({构造函数:function(){} 
})

var ServiceTest2 = ng.core.Component({选择器:“ st2”,
模板:“” 
})。Class({ 
构造函数:[Service5,function(s5){console.log(s5); 
}] 
})

var ServiceTest3 = ng.core.Component({选择器:“ st3”,
提供者:[ng.core.provide(Service5,{useFactory:function(){counter ++; 
return counter; 
}}))],
指令:[ServiceTest2],模板:“ <st2> </ st2>” 
})。Class({ 
构造函数:[Service5,function(s5){console.log(s5); 
}] 
})
用以下代码替换App组件的代码:
var App = ng .core.Component({选择器:“ app”,
指令:[卡,SampleComponent1,List,ListItem,SampleComponent2,SampleComponent3,SampleComponent4,SampleComponent6,SampleComponent7,SampleComponent8,SampleComponent9,SampleComponent11,SampleComponent13,ServiceTest1,ServiceTest3],
templateUrl:“ componentTemplates / app-template.html” 
})。Class({ 
构造函数:function(){} 
})
最后,在app-template.html文件的末尾,放置以下代码:
<st3> </ st3 > 
此代码的控制台输出如下:
2 此代码中的大多数内容都是不言自明的。我们使用的是提供程序,而不是viewProviders。ServiceTest2组件依赖于Service5,但是 它没有Service5的提供程序,因此Angular 2使用ServiceTest3提供的提供程序,因为ServiceTest3是其父级。如果ServiceTest3没有 Service5 的提供程序,则Angular 2会更进一步,并在App组件中寻找该提供程序。 


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

捷报频传!SVT和GA强势上线FCion交易所,领涨市场!

科技的发展日新月异,信息的交替层出不穷。2019年,区块链技术自诞生至此,已走过了十余年。在其发展过程中,造就了几次风口:第一次风口,大约在2013年,主要研究加密数字货币在各领域的应用,最后诞生了R......
eason1688 · 2019-11-11
258阅读 · 0赞赏 · 0问答

加密货币钱包现状和未来发展

在区块链应用场景中,钱包是第一个落地应用的项目,也是加密货币的关键基础设施,同时,每一种加密货币的交易方式都是仰仗钱包进行。目前,加密钱包种类繁多,据调查发现,有近4亿美元资金流向加密钱包业务,其中以......
smallfish · 2019-11-11
193阅读 · 0赞赏 · 0问答

BitDATA纽约大会强势来袭,Spinach带你亮点抢先看!

2019年,区块链行业热闹非凡。随着中国提出把区块链作为核心技术自主创新重要突破口,指出区块链技术应用已经延伸到数字金融、物联网、智能制造、供应链管理、数字资产交易等多个领域。在此背景之下,一场区块链......
eason1688 · 2019-11-09
526阅读 · 0赞赏 · 0问答

热钱包与冷钱包解决方案

随着市值的加密货币一天一天地增长,越来越多的人正在寻找更好的解决方案以将其硬币存储在加密钱包中。在谈论钱包时,更容易获得带有优惠券,美元钞票,旧收据,硬币等的破损皮革钱包的图像。但是,加密钱包是一种更......
老虎or猫咪 · 2019-11-08
231阅读 · 0赞赏 · 0问答

技术领先,合作共赢!Spinach的品牌崛起之路!

王兴在做美团成功后,曾经分享过一个“四纵三横”理论。讲解他当时是如何屡次踩对风口。纵轴就是关于技术的进化,而横轴是该技术对四个领域(游戏、资讯、社交、商务)的波及。当区块链的新技术兴起,在这四个领域的......
eason1688 · 2019-11-07
507阅读 · 0赞赏 · 0问答

GFC是什么,如何安装、注册GFC钱包?

什么是GFC?GFC是由Masternodes加入的开源对等 权益证明 加密货币。GFC货币使用与Dash&PivX相同的技术,但使用的算法已针对re仪业进行了重组。GFC的设计和开发使其成为支付全球......
呼近乎出 · 2019-11-06
352阅读 · 0赞赏 · 0问答

Moon

2176

LK币

16

粉丝

37

笔记

感谢"Moon"

这篇精彩的笔记,目前已经帮助

  • 0
  • 1
  • 2
  • 8
  • 0
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!