【问题标题】:@Input and other decorators and inheritance@Input 和其他装饰器和继承
【发布时间】:2016-02-25 15:03:00
【问题描述】:

我真的不明白对象绑定是如何工作的,所以如果有人能解释我是否可以在基类中使用@Input(),或者更好:装饰器和继承。 例如,如果每个表单都应该接收一个客户,那么我有一个基类:

export class AbstractCustomerForm{

@Input() customer;
...
}

然后我在一个实际的组件中扩展这个类:

export AwesomeCustomerForm extends AbstractCustomerForm implements OnInit{
    ngOnInit(){

        if(this.customer)
            doSomething();

    }
}

但这不起作用,客户永远不会得到设置:(

【问题讨论】:

    标签: angular angular2-inputs


    【解决方案1】:

    更新

    继承自2.3.0-rc.0起得到适当支持

    原创

    装饰器不被继承。它们需要直接应用于用作组件的类。子类上的装饰器被忽略。我看到它提到 @Input()@Output() 如果只有超类有它们而子类没有它们,它们就可以工作。

    【讨论】:

    • 所以我必须在每个客户表单中写下每个常见的输入:(
    • 是的,我希望他们最终能改进这一点,但这是一个复杂的话题,因为它需要与 Dart 和 JS 兼容,并且不能阻止大型应用程序的编译(例如 Google 实习生)。可能不会在 1.0 中修复。
    • 被这个烧死了——也很神秘的错误消息,抱怨一个未定义的字段。最终发现,除非子类上没有装饰器,否则装饰器不会被继承。似乎装饰器信息只是添加到类定义中,覆盖了超类中的任何内容,并且对装饰器的搜索不会沿着链条进行。无论如何,唯一的方法是将所有装饰属性从超类复制到子类。
    • 我觉得这是一个遗憾。继承这些装饰器感觉有点自然,我觉得这可以证明是一个非常好的架构奖励
    • 也许用于以后的版本。我的印象是他们只是不认为它是 2.0 版本的阻碍。
    【解决方案2】:

    我遵循的一个策略是这样的:

    @Component({
        selector: 'my-component',
        template: `......`,
        inputs: MyAbstractComponent.genericInputs
    })
    export class MyComponent extends MyAbstractComponent {
    
        @Input() width: number = 200;
        ........
    }
    

    地点:

    export abstract class MyAbstractComponent {
        public static genericInputs : string[] = ['base'];
        public base: String;
    }
    

    因此,MyComponent 将获得 base 以及 width 绑定。其实我觉得使用反射还是有提升空间的。

    【讨论】:

    • 一些 tslint 配置文件不允许使用输入。
    • 我试过这个,在 vscode 中得到了这个错误:“The Angular Language Service server crashed 5 times in the last 3 minutes”
    【解决方案3】:

    即使在 Angular 4.2.4 中,它在开发模式下也能正常工作。但是在进行产品构建 (ng build -prod) 时,它会失败:

    ERROR in Template parse errors:
    Can't bind to 'step' since it isn't a known property of 'app-textarea-step'.
    1. If 'app-textarea-step' is an Angular component and it has 'step' input, 
    then verify that it is part of this module.
    2. If 'app-textarea-step' is a Web Component then add 
    'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to 
    suppress this message.
    

    我的组件看起来像:

    abstract class StepComponent {
      @Input() step: BaseStep;
      @Output() next = new EventEmitter<string>();
      @Output() answer = new EventEmitter<Answer>();
    }
    
    abstract class SingleNextStepComponent extends StepComponent {
    
      onSubmit(answer: string) {
        // ConfirmStep heeft geen answer.
        if (answer) {
          this.answer.emit({ question: this.step.key, value: answer });
        }
        const step = this.step as SingleNextStep;
        this.next.emit(step.next);
      }
    }
    
    // Decorator inheritance works in standard build (ng build) but fails in production build (ng build -prod)
    // Workaround: inputs element on @Component that contains the inputs.....
    @Component({
      selector: 'app-textbox-step',
      templateUrl: './textbox-step.component.html',
      inputs: ['step']
    })
    export class TextboxStepComponent extends SingleNextStepComponent { }
    
    @Component({
      selector: 'app-textarea-step',
      templateUrl: './textarea-step.component.html',
    })
    export class TextareaStepComponent extends SingleNextStepComponent { }
    

    幸运的是,解决方法有效。添加到 TextBoxStepComponent 的输入阻止了这个失败,进入下一个,尚未提供“输入”。

    但 'ng build' 工作正常,不需要在 @Component 装饰器上输入...

    【讨论】:

    • 非常感谢!你知道这是否已经修复或者是否有错误票?
    【解决方案4】:

    我遇到了这个问题,只是想指出,从 Angular 2.3.0-rc.0 开始,这实际上是可能的。

    继承语义:

    装饰者:

    1) 以祖先第一顺序列出类及其父类的装饰器

    2) 只使用每种类型的最后一个装饰器(例如@Component / ...)

    构造函数参数:

    如果一个类继承自父类并且没有声明 一个构造函数,它继承父类的构造函数, 以及该父类的参数元数据。

    生命周期挂钩:

    遵循正常的类继承模型, 即父类的生命周期钩子将被调用 即使该方法没有在子类中被覆盖。

    https://github.com/angular/angular/commit/f5c8e09

    【讨论】:

      【解决方案5】:

      我在这里找到了一个可能的解决方案:

      https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7#.ca68alvcz

      基本上,它创建了一个自定义装饰器,通过反射简单地合并父装饰器和子装饰器。

      实际上我无法让它在基于 angular-cli 的项目上运行。

      【讨论】:

        【解决方案6】:

        装饰器不是继承的,但类是。所以我的解决方案是这样的:

        @Component({selector: 'a')
        class A {
          @Input() field;
        }
        
        @Component({selector: 'b', inputs: ['field']}
        class B extends A {
        }
        

        【讨论】:

          猜你喜欢
          • 2014-03-07
          • 2011-03-01
          • 2011-03-23
          • 2018-09-17
          • 1970-01-01
          • 2016-05-19
          • 2023-04-09
          • 2018-04-17
          • 2011-09-18
          相关资源
          最近更新 更多