天天看点

angular 自定义组件

参考文献:angular官网-自定义元素

1.使用 Angular CLI 可以自动为你的项目添加正确的脚本:

ng add @angular/elements --name=*your_project_name*
           

2.在app/components文件夹下新建loading文件夹,并创建loading.component.ts和loading.service.ts两个文件

loading.component.ts代码如下:

import { Component, OnInit, Input,EventEmitter, Output, OnChanges, SimpleChange, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-loading',
  template: `
  <div class="loading-box">
    <div class="loading">loading...</div>
  </div>
`,
styles: [`
  .loading-box{position: fixed;left:0;right:0;bottom:0;left:0;z-index: 999;}
  .loading{position: fixed;top:50%;left:50%;margin: -50px 0 0 -50px;width:100px;height:100px;background: rgba(0, 0, 0, .5);}
`]
})
export class LoadingComponent {
  
  constructor() {  } 

}
           

l3.loading.service.ts代码如下

import { Injectable, Output, EventEmitter } from '@angular/core';
import { NgElement, WithProperties } from '@angular/elements';
import { LoadingComponent } from './loading.component';

@Injectable({
  providedIn: 'root'
})
export class LoadingService {

  constructor() { }

  showLoading(){
       const loadEle: NgElement & WithProperties<LoadingComponent> = document.createElement('loading-element') as any;
       console.log(loadEle)
       document.body.appendChild(loadEle);
      return loadEle;
  }

  hideLoading(loadEle:(NgElement & WithProperties<LoadingComponent>) | string){
    // 删除所有
    if(typeof loadEle === 'string'){
      const eles = document.querySelectorAll('loading-element');
      if(eles.length){eles.forEach(ele =>document.body.removeChild(ele));}
      return;
    }
    
   // 删除当前
    const eles = document.querySelectorAll('loading-element');
    if(eles.length){
      eles.forEach(ele =>{
        ele === loadEle?document.body.removeChild(ele):''
      });
    }   
  }
}
           

4.app.module.ts代码如下:

@NgModule({
  declarations: [
    ...
    LoadingComponent,
    ...
  ],
  entryComponents: [
    LoadingComponent
  ],
  ...
})
           

5.app.component.ts代码如下(每个组件createCustomElement好像只能定义一次,就把他们放在app.component.ts中,):

constructor(injector: Injector){
    const LoadElement = createCustomElement(LoadingComponent, {injector});
    customElements.define('loading-element', LoadElement);
    
    const popupElement = createCustomElement(PopupComponent, {injector});
    customElements.define('popup-element', popupElement);
  }
           

6.在login.component.ts文件中使用:

// login.component.ts文件

constructor(private loading:LoadingService) { }

const loadEle = this.loading.showLoading(); // 显示
this.loading.hideLoading(loadEle); // 隐藏
 

           

可能会碰到的问题:

Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.     at NgElementImpl.NgElement [as constructor]

angular 自定义组件

可以通过修改

tsconfig.json

中的构建目标至es6解决该问题 ,如下,改成"target":"es6",改完后从新ng serve ,就可以正常了

angular 自定义组件