欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

动手写一个angular版本的Message组件的方法

程序员文章站 2022-05-07 14:12:03
学习一个框架或库的最好方法是看官方文档,并着手去写例子。最近在利用空闲的时间学习angular,那今天就尝试写一个message组件,并通过message服务动态加载mes...

学习一个框架或库的最好方法是看官方文档,并着手去写例子。最近在利用空闲的时间学习angular,那今天就尝试写一个message组件,并通过message服务动态加载message组件。
我所参与的项目基本是用jquery完成的。之前,在项目中自己动手写过一个简单的message插件,样子如下图。

动手写一个angular版本的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为需要注入的类。再梳理下整个过程:

  1. 提供providers
  2. 创建injector实例
  3. 创建componetfactory
  4. 使用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('成功了!');

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。