惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

zodream梦想开源/个人编程日记

angular 21 升级使用 signals 方案笔记-zodream梦想开源/个人编程日记 文件解析笔记-zodream梦想开源/个人编程日记 密码本开发笔记之读写与保存-zodream梦想开源/个人编程日记 基于 SkiaSharp 的轮廓获取-zodream梦想开源/个人编程日记 SkiaSharp 把 pixel byte[] 转成 SKBitmap-zodream梦想开源/个人编程日记 nas 使用 Docker 安装 gogs-zodream梦想开源/个人编程日记 复制 android 手机中的文件到电脑-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 升级 SiteServer CMS 并迁移到 Linux 服务器-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 周报:寻找优质的周刊-zodream梦想开源/个人编程日记 开发日志:对Markdown的代码块新增引用来源支持-zodream梦想开源/个人编程日记 周报:怎么写技术类的教程文章-zodream梦想开源/个人编程日记 css display:flex 布局尺寸超出问题-zodream梦想开源/个人编程日记 周报:SEO优化的思考-zodream梦想开源/个人编程日记 Edge 浏览器不适用 Edge Image Viewer 打开图片 -zodream梦想开源/个人编程日记 SEO 学习笔记(一) 内容来源-zodream梦想开源/个人编程日记 PHP 实现双因素身份认证(2FA)-zodream梦想开源/个人编程日记 winui3 自定义标题栏-zodream梦想开源/个人编程日记 WPF MVVM 获取List 多选数据-zodream梦想开源/个人编程日记 php 接入 WebAuthn 登录-zodream梦想开源/个人编程日记 Burp Suite 抓包-zodream梦想开源/个人编程日记 lnmp php集成环境安装包使用-zodream梦想开源/个人编程日记 js 进行在线编辑器开发-zodream梦想开源/个人编程日记 使用 indexnow 注意事项-zodream梦想开源/个人编程日记 Godot 使用字体图标 例如: Iconfont、FontAwesome-zodream梦想开源/个人编程日记 angular 15 对指定页面进行访问限制-zodream梦想开源/个人编程日记 CSS 使用 column-count 实现瀑布流出现内容分割的解决办法-zodream梦想开源/个人编程日记 angular 15 实现按下确认键,焦点移动到下一个表单或提交表单-zodream梦想开源/个人编程日记 input 确认按键事件在手机端不生效-zodream梦想开源/个人编程日记 C# 使用socket 进行通讯-zodream梦想开源/个人编程日记 Maui开发中Windows应用开启管理员权限-zodream梦想开源/个人编程日记 Maui 中自定义控件-zodream梦想开源/个人编程日记 TencentOS Server 3.1 安装 Nginx 1.23、PHP 8.2、MariaDB 10.11-zodream梦想开源/个人编程日记 angular 14 使用 ng-template 实现tree 结构显示-zodream梦想开源/个人编程日记 c# 动态安装和卸载dll-zodream梦想开源/个人编程日记 慎用 CompositionTarget.Rendering-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:数据初始化-zodream梦想开源/个人编程日记 源码编译 aseprite-zodream梦想开源/个人编程日记 记录一下字符串分隔split各语言之间的不同-zodream梦想开源/个人编程日记 c# Gzip解码无头内容-zodream梦想开源/个人编程日记 Windows 10 查看内存占用-zodream梦想开源/个人编程日记 UWP 使用 win2d:加阴影-zodream梦想开源/个人编程日记 清除 PowerShell 历史记录-zodream梦想开源/个人编程日记 c# 调用 c++ 的dll-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:遍历-zodream梦想开源/个人编程日记 Net Core 与 UWP 共用类开发-zodream梦想开源/个人编程日记 hashcat(二)找回rar解压密码-zodream梦想开源/个人编程日记 Godot 学习笔记(一)-zodream梦想开源/个人编程日记 升级vue3记录-zodream梦想开源/个人编程日记 angular 12 显示数学公式-zodream梦想开源/个人编程日记 js 监听按键事件-zodream梦想开源/个人编程日记 angular 12 ng-deep 使用注意事项-zodream梦想开源/个人编程日记 angular 16 动态生成组件-zodream梦想开源/个人编程日记 angular 12 动画执行完成事件-zodream梦想开源/个人编程日记 angular 12 全局搜索组件-zodream梦想开源/个人编程日记 angular 12 中单例 Service 的使用-zodream梦想开源/个人编程日记 js 实现一个正则替换-zodream梦想开源/个人编程日记 uwp win2d 使用-zodream梦想开源/个人编程日记 UWP Custom Control自定义控件开发-zodream梦想开源/个人编程日记 UWP 读取应用内资源-zodream梦想开源/个人编程日记 gin 使用笔记(二)出错点-zodream梦想开源/个人编程日记 gin 使用笔记(一)基础-zodream梦想开源/个人编程日记 angular 关于自定义组件事件传递-zodream梦想开源/个人编程日记 angular 11 怎么获取 Content-Disposition-zodream梦想开源/个人编程日记 apache 使用gzip 压缩 js、css-zodream梦想开源/个人编程日记 angular 11 返回上一页保留页面数据的思考-zodream梦想开源/个人编程日记 一个简单的HTML音视频播放器-zodream梦想开源/个人编程日记 Net Core 实现一个简单的分页功能-zodream梦想开源/个人编程日记 关于内容中的 @用户 加 话题 的一些想法-zodream梦想开源/个人编程日记 Github Host 更改-zodream梦想开源/个人编程日记 OBS-Studio 等录屏软件录制显示器内容的黑屏的解决方法-zodream梦想开源/个人编程日记 angular 11 FormBuilder 中 FormGroup 和 FormArray 使用-zodream梦想开源/个人编程日记 angular 11 ngrx/effects 使用理解-zodream梦想开源/个人编程日记 angular 11 ngrx/store 使用理解-zodream梦想开源/个人编程日记 angular 10 直接获取表单值-zodream梦想开源/个人编程日记 angular 10 使用 tinymce 编辑器-zodream梦想开源/个人编程日记 htaccess 搭配 angular 10 放在二级目录-zodream梦想开源/个人编程日记 微信小程序跨页面传值-zodream梦想开源/个人编程日记 js 对 FileList 进行文件过滤上传-zodream梦想开源/个人编程日记 angular自定义表单组件支持 formControlName-zodream梦想开源/个人编程日记 基于不同形式的json响应处理-zodream梦想开源/个人编程日记 flutter CupertinoPicker 使用不显示-zodream梦想开源/个人编程日记 CC协议-zodream梦想开源/个人编程日记 flutter margin 负值实现-zodream梦想开源/个人编程日记 win10添加删除开机自启项-zodream梦想开源/个人编程日记 Wallpager Engine 删除记录-zodream梦想开源/个人编程日记 angular10教程之http 拦截器-zodream梦想开源/个人编程日记 dpl 文件-zodream梦想开源/个人编程日记 微信小程序开发记录(一)真机无法进入页面-zodream梦想开源/个人编程日记 flutter 跳转页面操作上一页-zodream梦想开源/个人编程日记 Regex Generator 使用指南-zodream梦想开源/个人编程日记 go init函数-zodream梦想开源/个人编程日记 angular 9 升级 angular 10-zodream梦想开源/个人编程日记 kotlin AndroidManifest 注意事项-zodream梦想开源/个人编程日记 对于zodream 框架的优化的思考-zodream梦想开源/个人编程日记 flutter 页面滚动条-zodream梦想开源/个人编程日记 flutter swiper 使用-zodream梦想开源/个人编程日记
angular 14 替换 ComponentFactoryResolver 实现动态创建组件-zodream梦想开源/个人编程日记
2022-06-30 · via zodream梦想开源/个人编程日记

angular 14 替换 ComponentFactoryResolver 实现动态创建组件

需求

移植弹出框到 angular 项目中。

方案

直接使用其他项目依赖

比较常用的有以下两个

  1. ngx-toastr

  2. ng-bootstrap

但是通过查看源码,发现都使用使用 ComponentFactoryResolver 来实现组件的新建,然后通过document.body.appendChild 添加到页面上的,

但是,angular 文档中提示,ComponentFactoryResolver 不推荐使用。

Deprecated: Angular no longer requires Component factories. Please use other APIs where Component class can be used directly.
Note: since v13, dynamic component creation via ViewContainerRef.createComponent does not require resolving component factory: component class can be used directly.

12

自己实现

没有了 ComponentFactoryResolver, 那么就使用 ViewContainerRef.createComponent

主要思路:

  1. 新建一个容器组件,获取到 ViewContainerRef

    @Component({
     selector: 'app-dialog-container',
     template: '',
     styles: [''],
    })
    export class DialogContainerComponent {
    
     constructor(
         private service: DialogService,
         private viewContainerRef: ViewContainerRef,
     ) {
         this.service.containerRef = this.viewContainerRef;
     }
    }

    1234567891011121314

  2. 新建一个全局的服务提供者,

interface IDialogRef {
    id: any;
    element: ComponentRef<any>;
}

@Injectable({
    providedIn: 'root'
})
export class DialogService {
    private dialogItems: IDialogRef[] = [];
    public containerRef: ViewContainerRef;

    constructor(
        private injector: Injector,
    ) {

    }

    /**
     * 加载loading
     * @param option 
     * @returns loading 的id, 使用 remove(id: any) 进行关闭
     */
    public loading(option?: DialogLoadingOption): any {
        option = Object.assign({}, option, {
            time: 2000,
            closeable: true,
        });
        return this.createDailog(DialogLoadingComponent, option);
    }

    /**
     * 创建组件
     * @param component 
     * @param option 
     * @returns 
     */
    private createDailog<T>(component: Type<T>, option: any): any {
        const dialogId = ++ DialogService.guid;
        if (!this.containerRef) {
            return;
        }
        const dialogInjector = new DialogInjector(new DialogPackage(option, dialogId), this.injector);
        const dialogRef = this.containerRef.createComponent(component, {
            injector: dialogInjector
        });
        this.dialogItems.push({
            id: dialogId,
            element: dialogRef
        });
        return dialogId;
    }

    /**
     * 删除组件
     * @param i 
     */
    private removeAt(i: number) {
        const item = this.dialogItems[i];
        this.dialogItems.splice(i, 1);
        const dialogRef = item.element;
        dialogRef.destroy();
    }
}

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364

作为对比,ViewContainerRef.createComponentComponentFactoryResolver 使用更简单,而且更符合 angular 特色

constructor(
        private resolver: ComponentFactoryResolver,
        private applicationRef: ApplicationRef,
        private injector: Injector, 
        @Inject(DOCUMENT) private document: Document,
    ) { }


// 添加组件
const dialogFactory = this.resolver.resolveComponentFactory(component);
const dialogRef = dialogFactory.create(dialogInjector);
this.applicationRef.attachView(dialogRef.hostView);
this.document.body.appendChild(dialogRef.location.nativeElement);


// 删除组件
this.applicationRef.detachView(dialogRef.hostView);
this.document.body.removeChild(dialogRef.location.nativeElement);
this.dialogItems.splice(i);

12345678910111213141516171819

  1. 在组件内部实现删除功能
export class DialogMessageComponent implements OnDestroy {
    constructor(
        private data: DialogPackage<DialogMessageOption>,
        private service: DialogService,
    ) {

    }

    @HostListener('click')
    public close() {
        this.service.remove(this.data.dialogId);
    }
}

12345678910111213

  1. 以模块的方式提供
@NgModule({
    imports: [
        CommonModule,
    ],
    declarations: [
        ...COMPONENTS
    ],
    exports: [
        ...COMPONENTS
    ],
})
export class DialogModule {
    static forRoot(): ModuleWithProviders<DialogModule> {
        return {
            ngModule: DialogModule,
            providers: [
                DialogService
            ]
        };
    }
}

123456789101112131415161718192021

  1. 使用

第一步,在 app.module.ts 中导入

DialogModule.forRoot(),

1

第二步,在 app.component.ts 页面中添加容器

<app-dialog-container></app-dialog-container>

1

第三步,使用

constructor(
    private toastrService: DialogService) {
    this.toastrService.loading();
}

1234

总结

ViewContainerRef.createComponentComponentFactoryResolver 使用更简单,而且更符合 angular 特色,始终保持所有创建的内容在框架内。

完整代码请查看 Angular-ZoDream

转载请保留原文链接: https://zodream.cn/blog/id/231.html