转载:Angular5.x动态加载组件

146 阅读1分钟

Angular5.x动态加载组件

实战(原来写法)

<app-edit-classify [classifyOpt]="classifyOpt" [showClassifyModal]="showClassifyModal" [addClassifyType]="addClassifyType" [classifyDetail]="classifyDetail" (changeClassifyModal)="changeClassifyModal($event)"></app-edit-classify>

动态组件写法(具体解释看上头的链接哈)

constructor(
    private _resolver: ComponentFactoryResolver,
  ) { }
/**
* @desc 创建组件
* @param {string} type - 组件名
*/
public createComponent(type: string): any {
// 清空容器
this.componentContainer.clear();
// input 相当于@input()
// origin相当于子组件的值
// to相当于父组件传给子组件的值
const componentObj = {
  editClassifyDialog: {
    instance: EditClassifyComponent,
    input: [
      {
        origin: 'showClassifyModal',
        to: this.showClassifyModal
      },
      {
        origin: 'classifyOpt',
        to: this.classifyOpt
      },
      {
        origin: 'addClassifyType',
        to: this.addClassifyType
      },
      {
        origin: 'classifyDetail',
        to: this.classifyDetail
      }
    ],
    output: [
      {
        origin: 'changeClassifyModal',
        callFn: this.changeClassifyModal
      }
    ]
  },
}[type];

const factory = this.resolver.resolveComponentFactory(componentObj.instance);
const componentRef = this.componentContainer.createComponent(factory);

// @Input 输入属性处理
if (componentObj['input'].length) {
  componentObj['input'].forEach((item: any) => {
    componentRef.instance[item.origin] = item.to;
  });
}
// @Output 输出方法处理
if (componentObj['output'].length) {
  componentObj['output'].forEach((item: any) => {
    componentRef.instance[item.origin].subscribe(($event: any) => {
      item.callFn.bind(this)($event); // bind解决this指向问题
    });
  });
}
// 返回组件实例
return componentRef.instance;
}

public addNewClassify(classifyType: string): void {
    // 动态创建组件
    this.createComponent('editClassifyDialog').init();
}

tips: 如果使用form表单赋值没生效时 考虑使用脏检查

this._cdrSer.detach();
this.classifyForm.patchValue(this.classifyDetail);
this._cdrSer.detectChanges();

tips: 然后由于不走onchanges方法 导致视图不会动态渲染 所以有好多的问题