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

  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('成功了!');

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

您可能感兴趣的文章:

  • AngularJS使用ngMessages进行表单验证
  • Angular使用ng-messages与PHP进行表单数据验证
  • angular 基于ng-messages的表单验证实例
(0)

相关推荐

  • AngularJS使用ngMessages进行表单验证

    AngularJS 诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中.AngularJS有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入等等. 名称为"ngMessages"的module,通过npm install angular-messages进行安装.在没有使用ngMessages之前,我们可能这样写验证: <form name="

  • Angular使用ng-messages与PHP进行表单数据验证

    Angular中的ng-messages提供了更方便的表单数据验证服务. 本文代码主要基于<AngularJS权威教程>中关于ng-messages模块的说明,但原文中不乏错误以及没有后台代码和示例,所以简单的实现其功能.//别的地方也有错误,我一度怀疑我买了盗版书== 比如我们想与后台进行表单数据合法性验证并给出输入操作提示 HTML代码: <!DOCTYPE html> <html lang="en" ng-app="app">

  • angular 基于ng-messages的表单验证实例

    最近在学习angular,那么今天也算个学习笔记吧! html <div class="form-group" ng-class="{'has-error': myForm.myName.$touched && myForm.myName.$invalid}"> <label class="col-xs-2 control-label">name</label> <div class=&q

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

    学习一个框架或库的最好方法是看官方文档,并着手去写例子.最近在利用空闲的时间学习angular,那今天就尝试写一个message组件,并通过message服务动态加载message组件. 我所参与的项目基本是用jquery完成的.之前,在项目中自己动手写过一个简单的message插件,样子如下图. 那现在就使用angular(版本5.0.0)来实现message组件. message组件 message组件要根据传入的类型.消息和duration来显示.创建三个文件:message.compon

  • 自己动手写一个java版简单云相册

    动手写一个java版简单云相册,实现的功能是: 用户可以一次上传一个至多个文件. 用户可以下载其他人上传的图片. 用户可以查看其他所有人的图片. 用户只能删除通过自己IP上传的图片. 用到的技术: 文件上传下载.设计模式.Dom4j.xPath等. 先看下2个页面: 源代码: web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns=

  • Angular 封装并发布组件的方法示例

    一.封装组件 作为入门,这是一个非常简单的demo,但核心的接收使用者的输入@Input(),以及返回数据给使用者@Output()都实现了,所以有一定的借鉴意义. 目录结构:(部分目录不是框架中自动生成,二是后期添加,按照步骤进行即可.) 具体代码: html:(search.component.html) <input type="text" class="form-control" #info placeholder="{{informatio

  • 基于vue框架手写一个notify插件实现通知功能的方法

    简单编写一个vue插件,当点击时触发notify插件,dom中出现相应内容并且在相应时间之后清除,我们可以在根组件中设定通知内容和延迟消失时间. 1. 基础知识 我们首先初始化一个vue项目,删除不需要的组件和样式,主要针对src下一些初始化资源,有过vue项目基础的应该很容易理解,如果没有vue基础建议先熟悉每个初始化文件的作用. 关于vue中如何开发插件可以直接看vue官方文档,简单了解插件开发过程,vue插件文档. 现在我们在src目录下新建一个plugin文件夹,里面存放要开发的插件no

  • 手把手教你自己写一个js表单验证框架的方法

    在表单程序中,在页面上需要很多的Js代码来验证表单,每一个field是否必须填写,是否 只能是数字,是否需要ajax到远程验证,blablabla. 如果一个一个单独写势必非常的繁琐,所以我们的第一个目标就是构建一个类似DSL的东西, 用表述的语句而非控制语句来实现验证. 其次一个个单独写的话还有一个问题就是必须全部验证通过才能提交,但是单独验证会因为 这个特征而增加很多额外的控制代码,且经常会验证不全面.所以第二个目标就是能够全面 的整合整个验证的过程. 最后不能是一个无法扩展的一切写死的实现

  • 用Go写一个轻量级的ssh批量操作工具的方法

    前言 这是一个轮子. 大家都知道 Ansible是功能超级强大的自动化运维工具,十分的高大上.太高大上了以至于在低端运维有点水土不服,在于三点: Ansible 是基于 Python 的,而 Python 下的安装是有一堆依赖的...不要笑!对于很多使用 Win 的用户而言,光是装 Python, 装 pip 就够喝一壶的了. Ansible 的 paybook 所使用的 yaml 语法当然非常强大了.然而对于新人而言,刚入手是玩不转的,需要学习.虽然 Ansible 相比其他的自动化运维工具,

  • 分享一个自己动手写的jQuery分页插件

    工作需要一个JS分页插件,心想自己动手写一个吧,一来上网找一个不清楚代码结构的,出了问题难以解决,而且网上的插件所包含的功能太多,有些根本用不到,就没必要加载那段JS,二来想起没写过jQuery插件,就当练一下手了,好了,先看结果: http://demo.jb51.net/js/2014/EasyPage/ 简单说一下这个插件所要实现的功能 后台将查询出来的内容全部显示到页面上,这个插件要控制这些内容,使其一页一页显示.有上一页,下一页,首页,尾页的功能.在第一页时,上一页,首页要隐藏.在最后

  • 基于c# Task自己动手写个异步IO函数

    前言 对于服务端,达到高性能.高扩展离不开异步.对于客户端,函数执行时间是1毫秒还是100毫秒差别不大,没必要为这一点点时间煞费苦心.对于异步,好多人还有误解,如: 异步就是多线程:异步就是如何利用好线程池.异步不是这么简单,否则微软没必要在异步上花费这么多心思.本文就介绍异步最新的实现方式:Task,并自己动手写一个异步IO函数.只有了解了异步函数内部实现方式,才能更好的利用它. 对于c#,异步处理经过了多个阶段,但是对于现阶段异步就是Task,微软用Task来抽象异步操作.以后的异步函数,处

  • 80行代码写一个Webpack插件并发布到npm

    1. 前言 最近在学习 Webpack 相关的原理,以前只知道 Webpack 的配置方法,但并不知道其内部流程,经过一轮的学习,感觉获益良多,为了巩固学习的内容,我决定尝试自己动手写一个插件. 这个插件实现的功能比较简单: 默认清除 js 代码中的 console.log 的打印输出: 可通过传入配置,实现移除 console 的其它方法,如 console.warn.console.error 等: 2. Webpack 的构建流程以及 plugin 的原理 2.1 Webpack 构建流程

  • Message组件实现发财UI 示例详解

    目录 引言 支持的功能 使用方法 实现过程 如何实现不同类型的切换? 如何实现Message的弹出和消失? 如何实现往下排列而非堆叠? 如何实现添加和移除.message-active类? 如何将隐藏的Message从DOM树中移除 如何区分不同的Message? 最后的一个小细节 引言 最近在实现Message组件,就是会从屏幕顶端弹出的一个小提醒,过一会儿就消失了.我个人非常喜欢这个设计,感觉在后续的复用性也很高,于是就打算自己手写一个作为发财UI的组件 支持的功能 目前的Message有四

随机推荐