Angular2中的ViewChildren装饰器可以与Interfaces一起使用吗? [英] Can the ViewChildren Decorator in Angular2 work with Interfaces?

查看:51
本文介绍了Angular2中的ViewChildren装饰器可以与Interfaces一起使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照我对Angular 2的理解,ViewChildren装饰器允许组件获取其他组件或指令的查询.当我知道组件的特定类型时,我可以在Typescript中使用它,但是当我只知道组件的接口时,我希望能够获得QueryList.这样,我可以遍历视图组件.

The way I understand Angular 2, the ViewChildren decorator allows a Component to get a Query for other Components or Directives. I can get this to work in Typescript when I know the specific Type of the Component, but I would like to be able to get a QueryList when I just know the interface of the component. That way, I can iterate through the view components.

例如,在组件中我可能有这个:

For example, in the component I may have this:

@ViewChildren(Box) shapes: QueryList<Box>;

其中Box是一个具体的TypeScript类.我想要的是这样的:

where Box is a concrete TypeScript class. What I would like to have is this:

@ViewChildren(IShape) shapes: QueryList<IShape>;

其中,IShape是Box或其他组件可以实现的接口.这样,视图可以非常动态,并且我的代码仍然可以工作.有推荐的方法来解决这个问题吗?

where IShape is an interface that Boxes or other Components may implement. That way the view can be very dynamic and my code will still work. Is there a recommended way to handle this?

推荐答案

事实上,有一种方法可以执行您尝试做的事情,尽管可能不支持Typescript接口,因为GünterZöchbauer正确地认为它们没有这样做一旦将代码转换为javascript,就存在.

There is in fact a way to do something like what you are trying to do, albeit maybe not with Typescript interfaces, as Günter Zöchbauer is correct that they do not exist as such once the code is transpiled to javascript.

但是您可以使用父类.父级可能是一个抽象类.现在,我考虑了一下,如果将接口转换为运行时名称空间(我不知道它们是否存在),它们应该也能正常工作.

You can use a parent class however. The parent can probably be an abstract class. Now that I think about it, interfaces should work too IF they are transpiled into the runtime namespace, which I do not know if they are.

@Component({
  selector: 'square',
  providers: [provide(Shape, useExisting: forwardRef( ()=>Square )]
})
class Square extends Shape {}

请参阅此讨论.

https://github.com/angular/angular/issues/8580

现在,我想在下面为像我这样使用es5的用户留下自己的示例,并进行更彻底的用例演示.我试图平衡额外细节的数量,以使示例在整体上有意义,而不会变得多余.

Now I want to leave my own example below for those using es5 like me, and for the sake of a more thorough use-case demonstration. I tried to balance the amount of extra detail such that the example makes sense as a whole without getting extraneous.

如果您要对我的话题投反对票,请在这里停止阅读.

我需要在仪表板组件中执行一些自定义大小调整逻辑,并且我希望只有在父仪表板组件中执行了自定义大小调整逻辑后,几种不同类型的Chart指令才能重新呈现自己.我的某些图表实际上是组成部分,没有造成任何问题.使以下模式在es5中起作用所需的所有其他操作都是标准的.您无需在分配给NgModule的提供程序列表中包括app.Renderable.

I needed to do some custom resize logic in a dashboard component, and I wanted several different types of chart directive to rerender themselves only after I performed my custom resize logic in the parent dashboard component. Some of my charts were components actually and it caused no problems. Anything else you need to make the following pattern work in es5 is standard. You do not need to include app.Renderable in the list of providers given to your NgModule.

renderable.class.js

renderable.class.js

(function(app) {
    app.Renderable = ng.core.Class({
        constructor : [function Renderable() {}],
        render : function() {}
    });
})(window.app || (window.app = {}));

chart-one.directive.js

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 = {}));

chart-two.directive.js

chart-two.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 = {}));

dashboard.component.js

dashboard.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

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类以使其起作用.此外,您可以在提供程序列表中放置多个提供程序,从而允许查询您的组件或指令以获得我的多个令牌.因此,您可以说您可以用经典的javascript方式为实现ViewChild选择而实现"几个接口",但实际上并没有任何保证.

Now, in es5 javascript, it is actually unnecessary to extend the Renderable class in order for this to work. Furthermore, you can put more than one provider in your provider list, and thus allow your component or directive to be queried for my multiple tokens. Thus you could say you can "implement" several "interfaces" for the purposes of ViewChild selection in the classic javascript fashion of nothing being actually guaranteed.

这篇关于Angular2中的ViewChildren装饰器可以与Interfaces一起使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆