Angular 2自定义装饰器适用于RC4之后的版本,除了“多个组件”之外

时间:2016-10-12 14:03:30

标签: angular typescript

我正在研究我的Ionic 2组件ionic2-autocomplete,它最初是为RC.4和早期版本开发的,现在我正在尝试将它迁移到Angular 2 final。

作为原始设计的一部分,我让开发人员使用接受AutoCompleteItemtemplate的自定义装饰器templateUrl覆盖默认模板。 可以找到此装饰器的源代码here

正如您所看到的,我使用装饰器来保留组件所需的一些属性,同时让用户根据自己的需要设计组件。

现在,按照我在文档中写的完全相同的步骤,我尝试使用以下方法实现自定义模板:

import {AutoCompleteItem, AutoCompleteItemComponent} from 'ionic2-auto-complete';

@AutoCompleteItem({
  template : `<img src="build/images/flags/{{data.name}}.png" class="flag" /> <span [innerHTML]="data.name | boldprefix:keyword"></span>`,
})
export class CompTestItem extends AutoCompleteItemComponent{
}

在早期版本中完美运行(我还将CompTestItem添加到declerations数组中。

但由于某种原因,我现在遇到以下异常:

  

polyfills.js:3未处理的Promise拒绝:模板解析错误:   多个组件:AutoCompleteItemComponent,CompTestItem(“                      [错误 - &gt;];任务:Promise.then;   值:错误:模板解析错误:(...)错误:模板解析错误:   多个组件:AutoCompleteItemComponent,CompTestItem(“                      [ERROR - &gt;] http:// localhost:8101 / build / main.js:19480:19)       在RuntimeCompiler._compileTemplate(http://localhost:8101/build/main.js:27855:51)       在http://localhost:8101/build/main.js:27777:83       at Set.forEach(native)       在编译时(http://localhost:8101/build/main.js:27777:47)       at t.invoke(http://localhost:8101/build/polyfills.js:3:13400)       在e.run(http://localhost:8101/build/polyfills.js:3:10787)       在http://localhost:8101/build/polyfills.js:3:8889       at t.invokeTask(http://localhost:8101/build/polyfills.js:3:14029)       在e.runTask(http://localhost:8101/build/polyfills.js:3:11389)o @polyfills.js:3r @polyfills.js:3i @polyfills.js:3 polyfills.js:3   错误:未捕获(在承诺中):错误:模板解析错误:(...)o @   polyfills.js:3r @polyfills.js:3i @polyfills.js:3

我真的不知道为什么。任何人都可以知道为什么这个自定义装饰器不会在这个版本的Angular上工作? 为什么说我有多个组件?

谢谢!

1 个答案:

答案 0 :(得分:1)

更清楚地解释我的上述评论。看看你的装饰师

export function AutoCompleteItem( config: AutoCompleteItemMetadata ) {
  return function(cls: any) {
    const _reflect: any = Reflect;
    let annotations = _reflect.getMetadata('annotations', cls) || [];
    let extendedConfig: any = config;

    extendedConfig.selector = 'ion-auto-complete-item';
    annotations.push(new Component(extendedConfig));
    _reflect.defineMetadata('annotations', annotations, cls);

    return cls;
  };
}

您正在将每个组件的选择器设置为ion-auto-complete-item。所以在这种情况下

@AutoCompleteItem({
  template: defaultTemplate
})
export class AutoCompleteItemComponent {}

@AutoCompleteItem({})
export class ExtendedComponent extends AutoCompleteComponent {}

现在,您有两个具有相同选择器的组件。现在这一点无所谓。但当他们两个一起进入同一个房间时,Angular无法确定使用哪一个。

现在这可能不需要在早期的RC4中出现问题,因为限制比现在小。在使用仅限于组件

directives之前
@Component({
  directives: [ AutoCompleteItemComponent ]
})
class SomeComponent {}

在同一个组件中使用AutoCompleteItemComponentExtendedComponent可能很少见;所以没有冲突。

但不是我们使用模块,组件的范围变得更宽,这为更多冲突留下了空间。

也许你有一个共享模块,你导入到另一个模块

@NgModule({
  imports: [ FormsModule, CommonModule ],
  declarations: [ AutoCompleteItemComponent ],
  exports: [ AutoCompleteItemComponent ]
})
class SharedModule {}

@NgModule({
  imports: [ SharedModule ],
  declarations: [ ExtendedComponent, ComponentThatUsesExendedComponent ]
  exports: [ ComponentThatUsesExtendedComponent ]
})
class OtherModule {}

在上述情况下,您将收到错误消息,因为现在AutoComponentItemComponentExtendedComponent位于同一个房间。 Angular无法确定在ComponentThatUsesExendedComponent中使用哪一个,因此您会收到错误

  

多个组件AutoCompleteItemComponent,ExtendedComponent

此时我不知道你能做些什么来解决这个问题,但只是确保两个组件永远不会在同一个房间里,无论是显式还是隐式。更难的是组件类只能在一个模块中声明。

相关问题