按照我对 Angular 2 的理解,ViewChildren
装饰器允许组件获取其他组件或指令的查询。当我知道组件的特定类型时,我可以在 Typescript 中使用它,但是当我只知道组件的接口(interface)时,我希望能够获得 QueryList
。这样,我就可以遍历 View 组件。
例如,在组件中我可能有这个:
@ViewChildren(Box) shapes: QueryList<Box>;
其中 Box 是一个具体的 TypeScript 类。我想要的是:
@ViewChildren(IShape) shapes: QueryList<IShape>;
其中 IShape
是 Boxes 或其他组件可能实现的接口(interface)。这样 View 可以非常动态,我的代码仍然可以工作。有推荐的方法来处理这个问题吗?
最佳答案
事实上,有一种方法可以做您正在尝试做的事情,尽管可能不是使用 Typescript 接口(interface),因为 Günter Zöchbauer 是正确的,一旦代码被转换为 javascript,它们就不存在了。
但是您可以使用父类。父级可能是一个抽象类。现在我想起来了,如果接口(interface)被转换到运行时命名空间中,它们也应该可以工作,我不知道它们是否是。
@Component({
selector: 'square',
providers: [provide(Shape, useExisting: forwardRef( ()=>Square )]
})
class Square extends Shape {}
引用这个讨论。
https://github.com/angular/angular/issues/8580
现在我想为那些像我一样使用 es5 的人留下我自己的例子,并且为了更彻底的用例演示。我试图平衡额外细节的数量,以便示例作为一个整体有意义而不会变得无关紧要。
我需要在仪表板组件中执行一些自定义调整大小逻辑,并且我希望几种不同类型的图表指令仅在我在父仪表板组件中执行自定义调整大小逻辑后才重新呈现。我的一些图表实际上是组件,它没有引起任何问题。使以下模式在 es5 中工作所需的任何其他内容都是标准的。您不需要将 app.Renderable 包含在提供给您的 NgModule 的提供者列表中。
可渲染类.js
(function(app) {
app.Renderable = ng.core.Class({
constructor : [function Renderable() {}],
render : function() {}
});
})(window.app || (window.app = {}));
chart-one.directive.js
(function(app) {
app.ChartOneDirective = ng.core.Directive({
selector : 'canvas[chart-one]',
inputs : ['config:chart-one'],
providers : [{
provide: app.Renderable,
useExisting: ng.core.forwardRef(function(){
return app.ChartOneDirective;
}),
}]
}).Class({
extends : app.Renderable,
constructor : [/* injections */ function ChartOneDirective(/* injections */) {
// do stuff
}],
// other methods
render : function() {
// render the chart
}
});
})(window.app || (window.app = {}));
图表二.directive.js
(function(app) {
app.ChartTwoDirective = ng.core.Directive({
selector : 'canvas[chart-two]',
inputs : ['config:chart-two'],
providers : [{
provide: app.Renderable,
useExisting: ng.core.forwardRef(function(){
return app.ChartTwoDirective;
}),
}]
}).Class({
extends : app.Renderable,
constructor : [/* injections */ function ChartTwoDirective(/* injections */) {
// do stuff
}],
// other methods
render : function() {
// render the chart
}
});
})(window.app || (window.app = {}));
仪表板.component.js
(function(app) {
app.DashboardComponent = ng.core.Component({
selector : 'dashboard-component',
templateUrl : 'components/dashboard/dashboard.component.html',
host : {
'(window.resize)' : 'rerender()',
},
queries : {
renderables : new ng.core.ViewChildren(app.Renderable),
// other view children for resizing purposes
}
}).Class({
constructor : [/* injections */ function DashboardComponent(/* injections */) {
// do stuff
}],
resize : function() {
// do custom sizing of things within the dom
},
// other methods
rerender : function() {
this.resize();
this.renderables.forEach(function(r){
r.render();
});
}
});
})(window.app || (window.app = {}));
dashboard.component.html
<div #sizeMe>
<div class='canvas-wrapper'><canvas [chart-one]></canvas></div>
<div class='canvas-wrapper'><canvas [chart-two]></canvas></div>
<div class='canvas-wrapper'><canvas [chart-one]></canvas></div>
<div #sizeMeToo>
<div class='canvas-wrapper'><canvas [chart-two]></canvas></div>
<div class='canvas-wrapper'><canvas [chart-one]></canvas></div>
</div>
</div>
现在,在 es5 javascript 中,实际上没有必要扩展 Renderable 类来使其工作。此外,您可以在您的提供者列表中放置多个提供者,从而允许您的组件或指令查询我的多个 token 。因此,您可以说您可以“实现”几个“接口(interface)”,以便以经典的 javascript 方式选择 ViewChild,实际上没有任何保证。
关于angular - Angular2 中的 ViewChildren 装饰器可以与接口(interface)一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36286936/