参考文献: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]
可以通过修改tsconfig.json
中的构建目标至es6解决该问题 ,如下,改成"target":"es6",改完后从新ng serve ,就可以正常了