我正try 在一个Angular 的img元素上实现一个后备图像.为此,我创建了一个指令,该指令侦听img上的错误,并在发生错误时将其源替换为回退映像.

现在,我的图像的原始src属性是通过数据绑定设置的,这导致在原始和备用之间来回更改src的永久循环.我认为这是因为数据绑定不断地将src改回原处.

我的模板:

<img [src]="sanitizer.bypassSecurityTrustResourceUrl(building + url + with + variables)"
  fallbackImage="path/to/fallback.svg">

我的指令:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
    selector: 'img[fallbackImage]'
})
export class ImgFallbackDirective {

    constructor(private element: ElementRef) {}

    @Input('fallbackImage') fallbackImage: string;

    @HostListener('error') displayFallbackImage() {
        console.log('Before: ', this.element.nativeElement.src);
        this.element.nativeElement.src = this.fallbackImage || '';
        console.log('After: ', this.element.nativeElement.src);
    }
}

日志(log)记录来回更改的src.

推荐答案

我们可以插入一个设置了回退src的相邻元素(img),然后我们可以删除该指令所在的元素,这很有效!

@HostListener('error') displayFallbackImage() {
    if (this.isFirstLoad) {
      this.isFirstLoad = false;
      var img = document.createElement('img');
      img.src = this.fallbackImage;
      this.renderer.appendChild(this.element.nativeElement.parentNode, img);
      this.renderer.removeChild(
        this.element.nativeElement.parentNode,
        this.element.nativeElement,
        true
      );
    }
  }

完整代码

双手

import { Component } from '@angular/core';
import { bootstrapApplication, DomSanitizer } from '@angular/platform-browser';
import 'zone.js';
import { ImgFallbackDirective } from './test.指令';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ImgFallbackDirective],
  template: `
    <img [src]="sanitizer.bypassSecurityTrustResourceUrl(failingUrl)"
  fallbackImage="https://placehold.co/600x400">
  `,
})
export class App {
  failingUrl = 'https://placeeeeeeeeeehold.co/600x400';

  constructor(public sanitizer: DomSanitizer) {}

  setFailingUrl(value: any) {
    console.log(value);
    this.failingUrl = value;
  }
}

bootstrapApplication(App);

指令

import {
  Directive,
  ElementRef,
  HostListener,
  Input,
  Renderer2,
} from '@angular/core';

@Directive({
  selector: 'img[fallbackImage]',
  standalone: true,
})
export class ImgFallbackDirective {
  isFirstLoad = true;
  constructor(private element: ElementRef, private renderer: Renderer2) {}

  @Input('fallbackImage') fallbackImage!: string;

  @HostListener('error') displayFallbackImage() {
    if (this.isFirstLoad) {
      this.isFirstLoad = false;
      var img = document.createElement('img');
      img.src = this.fallbackImage;
      this.renderer.appendChild(this.element.nativeElement.parentNode, img);
      this.renderer.removeChild(
        this.element.nativeElement.parentNode,
        this.element.nativeElement,
        true
      );
    }
  }
}

Stackblitz Demo

Angular相关问答推荐

如何跨不同组件使用ng模板

如何在Angular 17 SSR中处理Swiper 11 Web组件事件

如何使用解析器处理Angular 路由中存储的查询参数以避免任何额外的导航?

@ngrx/调度时未定义存储操作

列表和映射的SCSS语法

Ngrx Select 器返回部分对象

在Angular中扩展多个类

从 Angular 应用程序中删除散列标签后无法从 Apache 访问 API

如何在 form.value 中禁用复选框

显示 1 个数据而不是所有 ngFor - Angular 11

如何在本地处理错误并跳过 Angular HTTP 拦截器?

过滤 ngfor Angular 的计数

将 html ngModel 值传递给服务Angular

Angular 2 中的 ChangeDetectionStrategy.OnPush 和 Observable.subscribe

Angular2 路由 VS ui-router-ng2 VS ngrx 路由

更改 Select 选项时获取当前值

Angular2 Pipes:输出原始 HTML

Angular - 是否有 HostListener-Events 列表?

Angular 2 Material Design 组件是否支持布局指令?

从 angular2 模板调用静态函数