如何使用Renderer2给动态创建的img元素添加appLazyLoadWithLoading指令
解决方案
为什么现有方案失效
Angular 框架中自定义指令的实例化依赖Angular自身的模板编译流程。你通过
Renderer2直接创建的是原生DOM元素,手动添加的appLazyLoadWithLoading只是普通DOM属性,Angular不会对这类脱离模板编译流程的DOM做指令识别,自然无法触发指令逻辑。另外$compile是AngularJS(1.x)的API,Angular(2+)中无该能力,所以无法生效。
推荐方案1:提前声明模板创建嵌入式视图(最简易)
该方案不需要额外处理编译逻辑,适合绝大多数业务场景:
- 首先在你的组件模板中提前声明img的模板片段:
<ng-template #lazyImgTpl let-element="element"> <img [src]="thumbnailMaker(element.url)" [alt]="element.name" [title]="element.name" appLazyLoadWithLoading > </ng-template>
- 在组件类中获取模板引用,动态创建视图:
import { ViewChild, TemplateRef, ViewContainerRef } from '@angular/core'; // 类内部代码 @ViewChild('lazyImgTpl', { static: true }) lazyImgTpl: TemplateRef<any>; constructor(private viewContainerRef: ViewContainerRef) {} // 创建img的逻辑处 addDynamicImg(element: any) { // 创建嵌入式视图,传入element参数 const imgView = this.viewContainerRef.createEmbeddedView(this.lazyImgTpl, { element }); // 将生成的img元素插入到目标容器 this.el.nativeElement.parentElement.append(...imgView.rootNodes); }
方案2:完全动态创建(无前置模板场景)
如果你的业务场景无法提前写模板,需要完全动态生成,可以创建临时动态组件承载带指令的img:
- 首先声明临时承载组件:
import { Component } from '@angular/core'; @Component({ template: `<img [src]="imgSrc" [alt]="imgAlt" [title]="imgTitle" appLazyLoadWithLoading >` }) class DynamicLazyImgComponent { imgSrc: string; imgAlt: string; imgTitle: string; }
- 确保你的
appLazyLoadWithLoading指令和DynamicLazyImgComponent都已经在当前所属模块的declarations数组中声明,或者在独立组件的imports中引入。 - 动态创建组件并提取img元素:
// Angular 13+ 写法 addDynamicImg(element: any) { // 创建动态组件实例 const componentRef = this.viewContainerRef.createComponent(DynamicLazyImgComponent); // 给组件赋值img相关参数 componentRef.instance.imgSrc = this.thumbnailMaker(element.url); componentRef.instance.imgAlt = element.name; componentRef.instance.imgTitle = element.name; // 触发变更检测完成渲染 componentRef.changeDetectorRef.detectChanges(); // 将生成的img插入目标容器 this.el.nativeElement.parentElement.append(componentRef.location.nativeElement.firstChild); // 可选:如果后续不需要操作组件可以手动销毁,也可随父组件自动销毁 // componentRef.destroy(); }
内容的提问来源于stack exchange,提问作者Behnam Aminazad
相关产品推荐
相关产品推荐

