我正在使用角度5.2.2,我想知道是否可以找到后代组件(嵌套深度2 +)。
例如:
FirstLevelComponent模板:
<first-level-component>
<second-level-component></second-level-component>
</first-level-component>
SecondLevelComponent模板:
<third-level-component></third-level-component>
我想在FirstLevelComponent中获取ThirdLevelComponent实例。
这个plunker展示了我正在尝试做的事情:https://plnkr.co/edit/9NsYmrsJMJEi0wofQReI?p=preview
编辑(2018/02/06)
一个选项可能是继承SecondLevelComponent以暴露ThirdLevelComponent,但我不想使用继承,它只限于一个深度级别。
经过一些检查,我努力创建一个帮助器来搜索后代组件。它使用ViewContainerRef:
import * as NgCore from '@angular/core';
@NgCore.Injectable()
export class FindDescendantsService {
constructor() { }
private findRecursive(container: any, type: any, results: any[]) {
if (!container) { return; }
if ('nodes' in container) {
container.nodes.forEach(n => {
if ('componentView' in n && n.componentView) {
if (n.componentView.component instanceof type) {
results.push(n.componentView.component);
}
this.findRecursive(n.componentView, type, results);
return;
}
if ('viewContainer' in n && n.viewContainer && n.viewContainer._embeddedViews && n.viewContainer._embeddedViews.length) {
n.viewContainer._embeddedViews.forEach(v => this.findRecursive(v, type, results));
return;
}
});
}
}
find(vcr: NgCore.ViewContainerRef, type: any) {
var view = vcr['_view'];
var results = [];
this.findRecursive(view, type, results);
return results;
}
}
然后在FirstLevelComponent中我可以这样做:
ngAfterContentInit(){
var thirdLevelInstances = this.findDescendantsService.find(this.viewContainerRef, ThirdLevelComponent);
}
我不太舒服,因为它使用了一些私有变量,可能会在将来的版本角度中改变名称/行为,但这现在满足了我的目标。我会等一段时间看看是否会出现更好的解决方案,如果没有,我认为这个助手可能就是答案......
答案 0 :(得分:1)
组件之间的角度通信只有父/子。如果您不能使用二级组件,则可以使用服务来完成此操作,如文档中所建议的那样。
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
答案 1 :(得分:1)
为了做到这一点,var dragHappened;
(function(H) {
var addEvent = H.addEvent;
H.Pointer.prototype.setDOMEvents = function() {
var pointer = this,
container = pointer.chart.container,
ownerDoc = container.ownerDocument;
container.onmousedown = function(e) {
dragHappened = false;
pointer.onContainerMouseDown(e);
};
container.onmousemove = function(e) {
pointer.onContainerMouseMove(e);
};
container.onclick = function(e) {
if (!dragHappened) {
pointer.onContainerClick(e);
}
};
(...)
}; // setDOMEvents
})(Highcharts);
(...)
plotOptions: {
series: {
point: {
events: {
drag: function() {
console.log('drag');
dragHappened = true;
},
click: function() {
console.log('click');
}
}
}
}
},
应该有一个second component
的实例。 E.g。
third component
但是,我不推荐这种方法。这会产生紧密耦合的组件,这也很难测试。您应该始终通过// First Component
@Component({
selector: 'first-comp',
template: `<second-comp></second-comp>`
})
export class FirstComponent {
@ViewChild(SecondComponent) secondComponent: SecondComponent;
doSomething() {
this.secondComponent.thirdComponent.doStuff();
}
}
// Second Component
@Component({
selector: 'second-comp',
template: `<third-comp></third-comp>`
})
export class SecondComponent{
@ViewChild(ThirdComponent) thirdComponent: ThirdComponent;
}
// Third Component
@Component({
selector: 'third-comp',
template: `<div>Hello World</div>`
})
export class ThirdComponent{
doStuff() {
// some logic here
}
}
和@Input
或某些服务传递您的数据。