动手写一个angular版本的Message组件的方法
学习一个框架或库的最好方法是看官方文档,并着手去写例子。最近在利用空闲的时间学习angular,那今天就尝试写一个message组件,并通过message服务动态加载message组件。
我所参与的项目基本是用jquery完成的。之前,在项目中自己动手写过一个简单的message插件,样子如下图。
那现在就使用angular(版本5.0.0)来实现message组件。
message组件
message组件要根据传入的类型、消息和duration来显示。创建三个文件:message.component.ts,message.component.html,message.component.css,代码如下。
//message.component.ts import {component,input,oninit,changedetectionstrategy} from '@angular/core'; import { trigger, state, style, transition, animate } from '@angular/animations'; const mapping={ success:'glyphicon-ok-sign', warning:'glyphicon-exclamation-sign', error:'glyphicon-exclamation-sign', info:'glyphicon-ok-circle' } @component({ selector:'upc-ng-message', templateurl:'./message.component.html', styleurls:['./message.component.css'], changedetection:changedetectionstrategy.onpush }) export class messagecomponent implements oninit{ ngoninit(): void { this.typeclass=['upc-message-' + this.msgtype]; this.typeiconclass=[mapping[this.msgtype]]; } @input() msgtype:'success' | 'info' | 'warning' | 'error'='info' @input() payload:string = '' private typeclass private typeiconclass }
<!--*message.component.html--> <div class="upc-message"> <div class="upc-message-content" [ngclass]="typeclass"> <i class="glyphicon" [ngclass]="typeiconclass"></i> {{payload}} </div> </div>
.upc-message { position: fixed; z-index: 1999; width: 100%; top: 36px; left: 0; pointer-events: none; padding: 8px; text-align: center; } .upc-message i { margin-right: 8px; font-size: 14px; top: 1px; position: relative; } .upc-message-success i { color: green; } .upc-message-warning i { color: yellow; } .upc-message-error i { color: red; } .upc-message-content { padding: 8px 16px; -ms-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 2px 8px #000000; -ms-box-shadow: 0 2px 8px #000000; box-shadow: 0 2px 8px #000000; box-shadow: 0 2px 8px rgba(0,0,0,.2); background: #fff; display: inline-block; pointer-events: all; }
componentloader
通过官方文档一节,可以了解动态创建组件需要通过componentfactoryresolver来完成。使用componentfactoryresolver创建componentfactory,再通过componentfactory的create方法创建组件。看官方文档中api的说明,componentfactory的create方法至少需要一个injector参数,而injector的创建在文档中也有提到,其中参数providers为需要注入的类。再梳理下整个过程:
- 提供providers
- 创建injector实例
- 创建componetfactory
- 使用componetfactory创建componentref
//componentfactory的create方法 create(injector: injector, projectablenodes?: any[][], rootselectorornode?: string|any, ngmodule?: ngmoduleref<any>): componentref<c> //使用injector的create创建injector实例 static create(providers: staticprovider[], parent?: injector): injector
为了代码的复用,这里创建通用的loader类来完成组件的动态创建。其中,attch方法用于初始化componetfactory(参数为组件类型);to方法用于标识组件的父容器;provider方法用于初始化可注入的类;create方法用于创建组件并手动变更检测;remove方法用于移除组件。
import { componentfactoryresolver, componentfactory, componentref, type, injector, provider, elementref } from '@angular/core'; export class componentloader<t>{ constructor(private _cfr: componentfactoryresolver, private _injector: injector) { } private _componentfactory: componentfactory<t> attch(componenttype: type<t>): componentloader<t> { this._componentfactory = this._cfr.resolvecomponentfactory<t>(componenttype); return this; } private _parent: element to(parent: string | elementref): componentloader<t> { if (parent instanceof elementref) { this._parent = parent.nativeelement; } else { this._parent = document.queryselector(parent); } return this; } private _providers: provider[] = []; provider(provider: provider) { this._providers.push(provider); } create(opts: {}): componentref<t> { const injector = injector.create(this._providers as any[], this._injector); const componentref = this._componentfactory.create(injector); object.assign(componentref.instance, opts); if (this._parent) { this._parent.appendchild(componentref.location.nativeelement); } componentref.changedetectorref.markforcheck(); componentref.changedetectorref.detectchanges(); return componentref; } remove(ref:componentref<t>){ if(this._parent){ this._parent.removechild(ref.location.nativeelement) } ref=null; } }
同时,为了便于loader的创建,再创建loaderfactory类,代码如下:
import { componentfactoryresolver, injector, injectable, elementref } from '@angular/core'; import { componentloader } from './component-loader.class'; @injectable() export class componentloaderfactory { constructor(private _injector: injector, private _cfr: componentfactoryresolver) { } create<t>(): componentloader<t> { return new componentloader(this._cfr, this._injector); } }
message service
message service提供显示message的api,代码如下:
import {injectable,injector} from '@angular/core'; import { componentloaderfactory } from '../component-loader/component-loader.factory'; import {messagecomponent} from './message.component'; import {componentloader} from '../component-loader/component-loader.class'; @injectable() export class messageservice{ constructor(private _clf:componentloaderfactory,private _injector:injector){ this.loader=this._clf.create<messagecomponent>(); } private loader:componentloader<messagecomponent> private createmessage(t,c,duration=2000){ this.loader.attch(messagecomponent).to('body'); const opts = { msgtype: t, payload:c }; const ref = this.loader.create(opts); ref.changedetectorref.markforcheck(); ref.changedetectorref.detectchanges(); let self=this; let st = settimeout(() => { self.loader.remove(ref); }, duration); } public info(payload,duration?) { this.createmessage('info',payload,duration); } public success(payload,duration?) { this.createmessage('success',payload,duration); } public error(payload,duration?) { this.createmessage('error',payload,duration); } public warning(payload,duration?) { this.createmessage('warning',payload,duration); } }
message.module
最后,增加message.module.ts。记得要把动态创建的组件添加到entrycomponents数组中。
import {ngmodule} from '@angular/core'; import { commonmodule } from '@angular/common'; import {messagecomponent} from './message.component'; import {messageservice} from './message.service'; import {componentloaderfactory} from '../component-loader/component-loader.factory'; @ngmodule({ imports:[commonmodule], declarations:[messagecomponent], providers:[messageservice,componentloaderfactory], entrycomponents:[messagecomponent], exports:[messagecomponent] }) export class messagemodule{ }
使用方法
注入messageservice,调用api使用message组件。
this._msgservice.success('成功了!');
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。