angular2动态加载组件

发表于: 2016年09月10 22:36
  • angular2 在发布了新的rc版本之后,已经弃用了DynamicComponentLoader动态加载组件的方法。*

angular2是google新推出的一套前端框架,相比angular1,angular2将主要通过组件来组织整个应用。 开发者可以将CSS,js,html封装成一个个功能独立的组件。这个组件有自己的标签,可以在其他组件中调用 也可以调用其他组件。通过组件化的开发大大提高了代码的复用能力和开发效率。由于当前angular2还处于 beta版,中文资料不是很多,自己在使用过程中也遇上过一些问题,遂将这些问题一并提取出来。

在angular2中如何动态加载组件?

angular2实际是提供了一个动态组件加载器(DynamicComponentLoader),这个模块中总共提供了三种方法 loadAsRoot,loadIntoLocation,loadNextToLocation 来实现不同场景下的组件动态加载需求。我们分别看看这三种方法的区别。

loadAsRoot(type: Type, overrideSelector: string, injector: Injector)

从全局的DOM节点根据选择器选择容器节点,并将组件加载到该容器节点的内部。通过这种方法加载,会导致数据绑定失效,可能需要自己做些处理。

<!-- 下面是页面代码的一部分,所有代码都省略了无关紧要的内容  index.html -->
<body>
    <myapp>Loading...</myapp>
    <div id="dynamic-container"></div>
</body>

// 下面是angular2中组件部分 appComponent.ts 
@Component({
    selector: 'dynamic-component',
    template: '<p>DynamicComponent</p>'
})
export class DynamicCom{
    constructor(){}
}

@Component({
    selector: 'myapp',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent{ 
    constructor(dcl: DynamicComponentLoader, injector: Injector) {
        dcl.loadAsRoot(DynamicCom, '#dynamic-container', injector);  // 动态加载组件
    }
}

执行之后,页面部分的节点是下面这个样子。

ng2_load_asroot

loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string)

从hostLocation中根据选择器选择节点,并将组件的实例加载到匹配到的节点后面, 下面是一段简单的样例代码

<!-- 下面是页面代码的一部分,所有代码都省略了无关紧要的内容  index.html -->
<body>
    <myapp>Loading...</myapp>
</body>

// 下面是angular2中组件部分 appComponent.ts 
@Component({
    selector: 'dynamic-component',
    template: '<p>DynamicComponent</p>'
})
export class DynamicCom{}

@Component({
    selector: 'myapp',
    template: '<h1 #title>My First Angular 2 App</h1>',
})
export class AppComponent implements OnInit{ 
    constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) {}
    ngOnInit() {
        // 这个例子中不能加加载函数放在construct中,因为这时myapp这个组建还没有创建完成,会报错的
        this.dcl.loadIntoLocation(DynamicCom, this.elementRef, 'title');
    }
}

渲染好的页面结构如下:

ng2_loadintolocation

现在还剩下最后一个方法loadNextToLocation,这个方法将需要动态渲染的组建加载到ElementRef表示的组件后面。且看下面这段代码

<!-- 下面是页面代码的一部分,所有代码都省略了无关紧要的内容  index.html -->
<body>
    <myapp>Loading...</myapp>
</body>

// 下面是angular2中组件部分 appComponent.ts 
@Component({
    selector: 'dynamic-component',
    template: '<p>DynamicComponent</p>'
})
export class DynamicCom{}

@Component({
    selector: 'myapp',
    template: '<h1 #title>My First Angular 2 App</h1>',
})
export class AppComponent implements OnInit{ 
    constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) {}
    ngOnInit() {
        this.dcl.loadNextToLocation(DynamicCom, this.elementRef);
    }
}

渲染好的页面结构如下:

ng2_loadintolocation

最后需要注意的是通过loadIntoLocation,loadNextToLocation这两个方法加载的动态组建,组建内定义的数据绑定等依然有效。 而通过loadAsRoot加载的组建,由于加载到全局的DOM节点中,则被加载的组建内部数据绑定监听则可能会失效。

如何控制这个动态组件

加载完组建之后,我们怎样去和组件进行交互呢? 由于这三个方法都是异步的,所以最终都会返回一个promise

其中ComponentRef.instance是动态生成的组件的实例,我们可以通过这个实例直接操作实例中的方法,对内部public类型的

变量赋值, 或者监听output的输出

如何销毁这个动态组件

销毁动态生成的组件就比较方便了,直接调用dispose()方法就可以了。

© 2018 - fluyy - 粤ICP备17114935号