Angular2组件工厂用于扩展组件

时间:2017-05-18 07:54:57

标签: javascript angular inheritance components extending

我正在尝试构建一个基于组件的应用程序,其中大多数代码应该可以重复使用,也可以使用其他一些样式表等。

目标是,我们有一些核心组件,我们也可以用于其他项目。它们应该是可扩展的,因此您可以自定义样式,功能等。

现在我正在尝试为我的问题找到解决方案: 我希望有一种机制,当我扩展组件时,应用程序已经加载了扩展组件而不是超级组件。我知道我可以为扩展组件创建一个新组件,但所以我必须在整个应用程序中调整代码。

一个小例子: 我有一个组件EditableList,具有基本样式和逻辑以及圆形按钮组件(ListButton)。 EditableList组件在App1中使用。

现在在App2中,我想扩展/覆盖ListButton组件,它不再是圆形的,而是矩形的(RectListButton)。但是,当我扩展组件时,我必须创建一个新组件(例如RectListButton),将EditableList的代码复制到一个新组件中,将ListButton更改为RectListButton(在EditableList组件中)并在我的App2中使用该新的EditableList2组件。

是否有可能让工厂认识到我已扩展该组件并加载扩展组件而不是基本组件? 这意味着对于我的示例,我只需要扩展ListButton并且EditableList组件自动检测,ListButton被覆盖并加载我的扩展RectListButton(或者可能是ListButtonExtended以获得更好的命名)。因此,我可以重用EditableList组件,而无需复制和修改它。

非常感谢!

此致 费边

1 个答案:

答案 0 :(得分:0)

这是一个适合我的解决方案

第1步

将核心组件放在核心模块中(应用1中的CoreModule,包含EditableList和ListButton组件)。

第2步

在某处,声明以下CustoModule功能

declare var Reflect : any;

export function CustomModule(annotations: any)
{
  return function (target: Function)
  {
    let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    let parentAnnotations = Reflect.getMetadata("annotations", parentTarget);

    let parentAnnotation = parentAnnotations[0];
    Object.keys(parentAnnotation).forEach(key =>
    {
      if (parentAnnotation[key] != null)
      {
        if (typeof annotations[key] === "function")
        {
          annotations[key] = annotations[key].call(this, parentAnnotation[key]);
        }
        else if (typeof Array.isArray(annotations[key]))
        {
          let mergedArrayItems = [];
          for (let item of parentAnnotation[key])
          {
            let childItem = annotations[key].find(i => i.name  == item.name);
            mergedArrayItems.push(childItem ? childItem : item);
          }

             annotations[key] = mergedArrayItems;
        }
        else if (annotations[key] == null)
        {  // force override in annotation base
          annotations[key] = parentAnnotation[key];
        }
      }
    });

    let metadata = new NgModule(annotations);

    Reflect.defineMetadata("annotations", [metadata], target);
  };
}

第3步

在app 2中,创建一个新的ListButton组件(在您的情况下为矩形组件),但将其称为ListButton(对于后续步骤很重要)。它必须与核心模块的ListButton

具有相同的选择器

第4步

然后在app2中有一些扩展CoreModule的App2ComponentModule模块。使用上面的CustomModule注释声明该模块(不要使用NgModule)

该新模块应声明并导出ListButton

@CustomModule({
  declarations: [    ListButton  ], //ListButton from app2
  exports: [  ListButton],//ListButton from app2
  bootstrap: [AppComponent]
})
export class App2ComponentModule extends CoreModule
{
}

第5步

在app 2中,从app2主模块导入App2ComponentModule。

自定义模块功能将做的是合并2个模块的注释,并在App2ComponentModule组件具有相同名称时替换CoreModule组件