14

我创建了Angular 库( ngx-wig ),我想提供一种通过使用插件来扩展其功能的能力。

在 Angular 中声明插件的最佳位置是什么?(可能类似于myLibModule.forRoot(..))什么类型的实例应该是插件本身?

我通过使用主模块的configProvider为我注册插件的每个插件添加模块,解决了AngularJs的相同问题。不是很喜欢这个解决方案,因为插件自己注册,但它应该是使用库的应用程序的责任。

更新:相关问题在 github 上打开。

4

1 回答 1

2

我认为您可以提供用户使用组件作为插件。该组件必须扩展您的抽象基础插件组件。

例如clear-styles插件可能看起来像

@Component({
  selector: `nw-clear-styles-button`,
  template: `
    <button (click)="clearStyles($event)" 
        [disabled]="editMode || disabled" 
        class="nw-button clear-styles" title="Clear Styles">
      Clear Styles
    </button>`
})
export class NwClearStylesButtonComponent extends Ng2WigPluginComponent {
  constructor() {
    super();
  }

  clearStyles() {
    const div = document.createElement('div');
    div.innerHTML = this.content;
    this.contentChange.emit(div.textContent);
  }
}

format插入

@Component({
  selector: `nw-formats-button`,
  template: `
    <select class="nw-select"
            [(ngModel)]="format"
            (ngModelChange)="execCommand('formatblock', format.value)"
            [disabled]="editMode || disabled">
      <option *ngFor="let format of formats" [ngValue]="format">{{ format.name }}</option>
    </select>
  `
})
export class NwFormatButtonComponent extends Ng2WigPluginComponent {
  formats = [
    {name: 'Normal text', value: '<p>'},
    {name: 'Header 1', value: '<h1>'},
    {name: 'Header 2', value: '<h2>'},
    {name: 'Header 3', value: '<h3>'}
  ];

  format = this.formats[0];

  constructor() {
    super();
  }
}

Ng2WigPluginComponent您的库提供的抽象基类在哪里:

export abstract class Ng2WigPluginComponent {
  execCommand: Function;
  editMode: boolean;
  content: string;

  editModelChange: EventEmitter<boolean> = new EventEmitter();
  contentChange: EventEmitter<string> = new EventEmitter();
}

因此用户可以轻松地使用在基类中声明的属性。

要注册此类插件,我们可以使用您提到的forRoot方法。为此,您需要

1)如下配置你的库模块:

ng2wig.module.ts

@NgModule({
 ...
})
export class Ng2WigModule {
  static forRoot(entryComponents: CustomButton[]) {
    return {
      ngModule: Ng2WigModule,
      providers: [
        Ng2WigToolbarService,
        {provide: NG_WIG_CUSTOM_BUTTONS, useValue: entryComponents},
        {provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: entryComponents},
      ]
    };
  }
}

在哪里

  • NG_WIG_CUSTOM_BUTTONS是您的全局库令牌,用于识别库内提供的插件

ng2wig-toolbar.service.ts

@Injectable()
export class Ng2WigToolbarService {
  constructor(@Optional() @Inject(NG_WIG_CUSTOM_BUTTONS) customButtons: CustomButton[]) {
    if (customButtons) {
      customButtons.forEach(plugin => this.addCustomButton(plugin.pluginName, plugin.component));
    }
  }
  • ANALYZE_FOR_ENTRY_COMPONENTS是能够动态加载插件的角度全局令牌

2)在你的模块的声明NwClearStylesButtonComponent数组中声明AppModule

3)将其传递给Ng2WigModule.forRoot方法

Ng2WigModule.forRoot([
   { pluginName: 'clear-styles', component: NwClearStylesButtonComponent },
   { pluginName: 'format', component: NwFormatButtonComponent }
]) 

然后你的主要任务是使用ComponentFactoryResolverand动态生成你的组件ViewContainerRef(见ng2wig-plugin.directive.ts下面的 plunker)

Plunker 示例

于 2017-06-26T08:56:22.713 回答