【问题标题】:Angular setting img[src] to null even thought it has valueAngular 将 img[src] 设置为 null 甚至认为它具有价值
【发布时间】:2019-09-07 13:33:18
【问题描述】:

我已经创建了一对指令,一个来

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:

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

我是否遗漏了任何行为,或者这是角度错误?

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

【问题讨论】:

  • 您期望的行为是什么?
  • @FedericoGalfione 看看,我已经编辑了问题(就在代码之后)
  • 为什么需要GetSrcDirective?您可以绑定到 src 并实现相同的目的。那么指令冲突就没有问题了。从两个指令中操作 src 属性的操作非常棘手。

标签: angular


【解决方案1】:

我已与 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 希望我们这样做的方式。

【讨论】:

    猜你喜欢
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多