角度img [src]设置为null甚至认为它有价值

时间:2019-04-17 10:16:04

标签: angular

我创建了一对指令,一个对

HTML

<div>
    <h3>Both</h3>
    <img
        sGetSrc="//via.placeholder.com/120x60?text=Good"
        sFallback="//via.placeholder.com/120x60?text=Fallback"
    >
</div>

GetSrcDirective [sGetSrc]

export class GetSrcDirective {
    @HostBinding('src') @Input('sGetSrc') image!: string;
}

FallbackDirective [sFallback]

export class FallbackDirective {
    @HostBinding('class.no-image') hasError = false;

    private originalSrc!: string;
    @Input('src') set src(value: string) {
        if (!value) { return; }
        if (value == this.originalSrc) { return; }

        this.hasError = false;
        this.originalSrc = value;
    }
    @Input() sFallback!: string;

    @HostBinding('src') get currentSrc(): string {
        if (this.hasError) {
            return this.sFallback;
        } else {
            return this.originalSrc;
        }
    }

    @HostListener('error')
    failure() {
        this.hasError = true;
    }
}

从此代码中,我希望它将src设置为GetSrcDirective指令的某个值,然后FallbackDirective应该在发生错误的情况下更改img [src]。

但是现在以某种方式将src设置为null,确切地说,我已经进行了一些调试,并且按休整的顺序进行了这些操作,从而导致将src设置为null:

  • 构建AppComponent
  • 创建GetSrcDirective
    • sGetSrc设置为image
    • 将图像src设置为image
  • 创建FallbackDirective
    • 将调用Input('src')设置为image
    • 将图像src设置为value
  • 完成休息
  • 现在调试周期开始运行
  • sGetSrc设置为 null
  • 将img src设置为null
  • 正在加载图片...
  • img [src = null]调用错误
  • FallbackDirective做出反应并将img [src]更新为后备图片

我是否错过任何行为,还是这个角度误差?

Stackblitz:https://stackblitz.com/edit/angular-pvqy4g

1 个答案:

答案 0 :(得分:0)

我已经与Angular团队交谈,他们非常友好地回应:

  

总的来说,我不相信这段代码会按您的预期工作。在Angular中,一个指令无法将输入设置为另一指令-例如,如果元素具有两个指令,并且其中一个指令具有@HostBinding('[src]'),则不会导致另一指令的@Input('src')被更新。唯一可以更新@Input的东西是模板中的绑定表达式。

有了这一点,我意识到,解决它的简单方法就是让指令彼此通信。

GetSrcDirective [sGetSrc]

export class GetSrcDirective {
    @HostBinding('src') srcBinding!: string;
    @Input('sGetSrc') set image(source: string) {
        this.srcBinding = source
        if (this.fallbackDirective) {
            this.fallbackDirective.setSource(source);
        }
    }

    constructor(
        @Host() @Optional() fallbackDirective: FallbackDirective,
    ) { }

}

FallbackDirective [sFallback]

export class FallbackDirective {
    @HostBinding('class.no-image') hasError = false;

    private originalSrc!: string;
    @Input('src') set src(value: string) {
        if (!value) { return; }
        this.setSource(value);
    }
    @Input() sFallback!: string;

    @HostBinding('src') get currentSrc(): string {
        if (this.hasError) {
            return this.sFallback;
        } else {
            return this.originalSrc;
        }
    }

    setSource(source: string) {
        if (value == this.originalSrc) { return; }

        this.hasError = false;
        this.originalSrc = value;
    }

    @HostListener('error')
    failure() {
        this.hasError = true;
    }
}

重要的部分是@Host() @Optional() fallbackDirective: FallbackDirective,它说,FallbackDirective位于同一元素上(如果存在)。然后,如果我们有它,我们将直接对其进行更新,从而解决问题。这也是Angular希望我们这样做的方式。