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

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
博客园 - 叶小钗
Recent Announcements
Recent Announcements
人人都是产品经理
人人都是产品经理
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
Hugging Face - Blog
Hugging Face - Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
美团技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
F
Fortinet All Blogs
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
H
Heimdal Security Blog
有赞技术团队
有赞技术团队
The Cloudflare Blog
S
Secure Thoughts
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
The Blog of Author Tim Ferriss
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
Schneier on Security
Schneier on Security
N
News and Events Feed by Topic
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - Franky
T
Tenable Blog
The Last Watchdog
The Last Watchdog
腾讯CDC
量子位
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
雷峰网
雷峰网
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
S
Securelist
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
InfoQ
Spread Privacy
Spread Privacy
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hackread – Cybersecurity News, Data Breaches, AI and More

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

文件解析笔记-zodream梦想开源/个人编程日记 密码本开发笔记之读写与保存-zodream梦想开源/个人编程日记 SkiaSharp 把 pixel byte[] 转成 SKBitmap-zodream梦想开源/个人编程日记 nas 使用 Docker 安装 gogs-zodream梦想开源/个人编程日记 复制 android 手机中的文件到电脑-zodream梦想开源/个人编程日记 周报:寻找优质的周刊-zodream梦想开源/个人编程日记 开发日志:对Markdown的代码块新增引用来源支持-zodream梦想开源/个人编程日记 周报:怎么写技术类的教程文章-zodream梦想开源/个人编程日记 css display:flex 布局尺寸超出问题-zodream梦想开源/个人编程日记 周报:SEO优化的思考-zodream梦想开源/个人编程日记 Edge 浏览器不适用 Edge Image Viewer 打开图片 -zodream梦想开源/个人编程日记 SEO 学习笔记(一) 内容来源-zodream梦想开源/个人编程日记 PHP 实现双因素身份认证(2FA)-zodream梦想开源/个人编程日记 WPF MVVM 获取List 多选数据-zodream梦想开源/个人编程日记 Burp Suite 抓包-zodream梦想开源/个人编程日记 使用 indexnow 注意事项-zodream梦想开源/个人编程日记 Godot 使用字体图标 例如: Iconfont、FontAwesome-zodream梦想开源/个人编程日记 angular 15 对指定页面进行访问限制-zodream梦想开源/个人编程日记 CSS 使用 column-count 实现瀑布流出现内容分割的解决办法-zodream梦想开源/个人编程日记 input 确认按键事件在手机端不生效-zodream梦想开源/个人编程日记 C# 使用socket 进行通讯-zodream梦想开源/个人编程日记 Maui开发中Windows应用开启管理员权限-zodream梦想开源/个人编程日记 Maui 中自定义控件-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++ 程序笔记:遍历-zodream梦想开源/个人编程日记 Net Core 与 UWP 共用类开发-zodream梦想开源/个人编程日记 hashcat(二)找回rar解压密码-zodream梦想开源/个人编程日记 Godot 学习笔记(一)-zodream梦想开源/个人编程日记 angular 12 显示数学公式-zodream梦想开源/个人编程日记 js 监听按键事件-zodream梦想开源/个人编程日记 angular 12 ng-deep 使用注意事项-zodream梦想开源/个人编程日记 angular 12 动画执行完成事件-zodream梦想开源/个人编程日记 angular 12 中单例 Service 的使用-zodream梦想开源/个人编程日记 js 实现一个正则替换-zodream梦想开源/个人编程日记 uwp win2d 使用-zodream梦想开源/个人编程日记 UWP 读取应用内资源-zodream梦想开源/个人编程日记 gin 使用笔记(二)出错点-zodream梦想开源/个人编程日记 gin 使用笔记(一)基础-zodream梦想开源/个人编程日记 angular 关于自定义组件事件传递-zodream梦想开源/个人编程日记 apache 使用gzip 压缩 js、css-zodream梦想开源/个人编程日记 关于内容中的 @用户 加 话题 的一些想法-zodream梦想开源/个人编程日记 Github Host 更改-zodream梦想开源/个人编程日记 OBS-Studio 等录屏软件录制显示器内容的黑屏的解决方法-zodream梦想开源/个人编程日记 angular 11 ngrx/effects 使用理解-zodream梦想开源/个人编程日记 angular 11 ngrx/store 使用理解-zodream梦想开源/个人编程日记 angular 10 直接获取表单值-zodream梦想开源/个人编程日记 htaccess 搭配 angular 10 放在二级目录-zodream梦想开源/个人编程日记 微信小程序跨页面传值-zodream梦想开源/个人编程日记 js 对 FileList 进行文件过滤上传-zodream梦想开源/个人编程日记 angular自定义表单组件支持 formControlName-zodream梦想开源/个人编程日记 flutter CupertinoPicker 使用不显示-zodream梦想开源/个人编程日记 CC协议-zodream梦想开源/个人编程日记 flutter margin 负值实现-zodream梦想开源/个人编程日记 win10添加删除开机自启项-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梦想开源/个人编程日记 flutter API请求-zodream梦想开源/个人编程日记 网站体检之xss攻击-zodream梦想开源/个人编程日记 GitHub 下载慢怎么办-zodream梦想开源/个人编程日记 小程序商城开发总结-zodream梦想开源/个人编程日记 gulp-vue2mini 更新日志-zodream梦想开源/个人编程日记 UWP TextBlock 换行-zodream梦想开源/个人编程日记 js 数组排序 sort-zodream梦想开源/个人编程日记 抛弃create.js 改用pixi.js-zodream梦想开源/个人编程日记 后台列表页进阶之路-zodream梦想开源/个人编程日记 局域网文件传输工具-zodream梦想开源/个人编程日记 angular9教程之PullToRefresh-zodream梦想开源/个人编程日记 c# 添加防火墙例外端口-zodream梦想开源/个人编程日记 c# 获取局域网ip-zodream梦想开源/个人编程日记 angular9教程之自定义部件及获取页面元素-zodream梦想开源/个人编程日记 netcore 依赖注入 AddTransient、AddScoped、AddSingleton-zodream梦想开源/个人编程日记 createjs 实现封装 drawImage-zodream梦想开源/个人编程日记 笔记(200521)游戏及玩家分类-zodream梦想开源/个人编程日记 关于 MasterDetail 模式页面收集-zodream梦想开源/个人编程日记 怎么写日记(一)格式规范-zodream梦想开源/个人编程日记 angular9教程之路由-zodream梦想开源/个人编程日记 PHP 常用框架-zodream梦想开源/个人编程日记 angular9教程之监听子路由变化-zodream梦想开源/个人编程日记 angular9教程之添加启动加载动画-zodream梦想开源/个人编程日记 angular9教程之分模块开发-zodream梦想开源/个人编程日记 angular9教程之使用-zodream梦想开源/个人编程日记 create.js 开发小游戏(二)蒙版-zodream梦想开源/个人编程日记 createjs 游戏结束后重新开始 Tween 补间动画无效-zodream梦想开源/个人编程日记 SEO(二)关键词优化试验-zodream梦想开源/个人编程日记
angular 16 动态生成组件-zodream梦想开源/个人编程日记
zodream · 2021-07-02 · via zodream梦想开源/个人编程日记

angular 16 动态生成组件

需求

在页面中生成一个确认弹窗

新的实现方式

第一步,获取需要的工具

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

    public containerRef: ViewContainerRef; //需要从Component中获取,然后传递进来
    constructor(
        private injector: Injector,
    ) { }
}

12345678910

ViewContainerRef 的获取方式

  1. 第一种在 Component 初始化时获取

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

    1234567891011121314

  2. template 中通过 ng-container 获取

    @Component({
     selector: 'app-dialog-container',
     template: '<ng-container #modalVC></ng-container>',
     styles: [''],
    })
    export class DialogContainerComponent implements AfterViewInit {
    
     @ViewChild('modalVC', {read: ViewContainerRef})
     private viewContainerRef: ViewContainerRef;
    
     constructor(
         private service: DialogService,
     ) {
    
     }
    
     ngAfterViewInit(): void {
         this.service.containerRef = this.viewContainerRef;
     }
    }

    1234567891011121314151617181920

主要区别:就是增加的元素节点为兄弟节点,所以,第一种添加的弹窗是在外面的,不受 app-dialog-container 中的样式影响;第二种是作为子元素添加的,受样式影响

第二步,实现动态生成组件

component 为组件的类名

const dialogRef = this.containerRef.createComponent(component, {
    injector: this.injector
});

// dialogRef.instance 就是组件的实例 

12345

第三步,移除组件

如果需要在组件初始化,自动注入值或传值,则需要自定义 injector

import { InjectFlags, Injector, ProviderToken } from '@angular/core';

// 这个类是传值的载体
export class DialogPackage<T = any> {
    constructor(
        public data: T,
        public dialogId: any,
    ) {
    }
}

// 这是自定义的注射器
export class DialogInjector<T> implements Injector {

    constructor(
        private data: DialogPackage,
        private parentInjector: Injector
      ) {}

    get<T>(token: ProviderToken<T>, notFoundValue?: T, option?: InjectOptions): T;
    get(token: any, notFoundValue?: any);
    get(token: any, notFoundValue?: any, flags?: any): any {
        if (token === DialogPackage) {
            return this.data;
          }
          return this.parentInjector.get<T>(token, notFoundValue, flags);
    }

}

1234567891011121314151617181920212223242526272829

第二步需要修改

const dialogInjector = new DialogInjector(new DialogPackage(option, dialogId), this.injector);
const dialogRef = this.containerRef.createComponent(component, {
    injector: dialogInjector
});

// dialogRef.instance 就是组件的实例 

123456

在组件中接收值

export class DialogConfirmComponent {

    constructor(
        private data: DialogPackage<DialogConfirmOption>,
        private service: DialogService,
    ) {

    }
}

123456789

过时实现代码

第一步,获取需要的工具

export class DialogService {

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


}

1234567891011

第二步,实现动态生成组件

component 为组件的类名

const dialogFactory = this.resolver.resolveComponentFactory(component);
const dialogRef = dialogFactory.create(this.injector);
// 正式添加到程序和添加到页面上,才能显示
this.applicationRef.attachView(dialogRef.hostView);
this.document.body.appendChild(dialogRef.location.nativeElement);

// dialogRef.instance 就是组件的实例 

1234567

第三步,移除组件

this.applicationRef.detachView(dialogRef.hostView);
this.document.body.removeChild(dialogRef.location.nativeElement);

12

如果需要在组件初始化,自动注入值或传值,则需要自定义 injector

import { InjectFlags, Injector, ProviderToken } from '@angular/core';

// 这个类是传值的载体
export class DialogPackage<T = any> {
    constructor(
        public data: T,
        public dialogId: any,
    ) {
    }
}

// 这是自定义的注射器
export class DialogInjector<T> implements Injector {

    constructor(
        private data: DialogPackage,
        private parentInjector: Injector
      ) {}

    get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T;
    get(token: any, notFoundValue?: any);
    get(token: any, notFoundValue?: any, flags?: any): any {
        if (token === DialogPackage) {
            return this.data;
          }
          return this.parentInjector.get<T>(token, notFoundValue, flags);
    }

}

1234567891011121314151617181920212223242526272829

第二步需要修改

const dialogFactory = this.resolver.resolveComponentFactory(component);
// 这里的option 可以是任何值
const dialogInjector = new DialogInjector(new DialogPackage(option, dialogId), this.injector);
const dialogRef = dialogFactory.create(dialogInjector);
// 正式添加到程序和添加到页面上,才能显示
this.applicationRef.attachView(dialogRef.hostView);
this.document.body.appendChild(dialogRef.location.nativeElement);

// dialogRef.instance 就是组件的实例 

123456789

在组件中接收值

export class DialogConfirmComponent {

    constructor(
        private data: DialogPackage<DialogConfirmOption>,
        private service: DialogService,
    ) {

    }
}

123456789

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