Aurelia:自定义属性的主要 属性 的数据绑定问题

Aurelia: data binding issue with the primary property of a custom attribute

我已经学习 Aurelia 几个星期了,我似乎遇到了自定义属性的数据绑定问题。

我创建了以下 square 自定义属性(基于 "Templating:Custom Attributes" guide on the Aurelia website 中的示例):

square.ts:

import { bindable, autoinject } from "aurelia-framework";

@autoinject
export class SquareCustomAttribute {
  @bindable sideLength = "100px";
  @bindable color = "red";

  constructor(private element: Element) {
    this.sideLengthChanged(this.sideLength);
    this.colorChanged(this.color);
  }

  sideLengthChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.width = this.element.style.height = newValue;
    }
  }

  colorChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.backgroundColor = newValue;
    }
  }
}

我希望这个自定义属性无需显式绑定就可以使用,在这种情况下它应该使用默认值,就像在这个消费视图中一样:

app.html:

<template>
  <require from="./square"></require>
  <div square></div>
</template>

上面的代码工作正常。它将 div 呈现为边长为 100px 且背景为红色的正方形。

当我像这样将 SquareCustomAttributecolor 属性 设置为主 属性(使用 @bindable 的配置对象参数)时出现问题:

已更新square.ts:

import { bindable, autoinject } from "aurelia-framework";

@autoinject
export class SquareCustomAttribute {
  @bindable sideLength = "100px";
  @bindable({ primaryProperty: true }) color = "red";

  constructor(private element: Element) {
    this.sideLengthChanged(this.sideLength);
    this.colorChanged(this.color);
  }

  sideLengthChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.width = this.element.style.height = newValue;
    }
  }

  colorChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.backgroundColor = newValue;
    }
  }
}

出于某种原因,将 color 设置为自定义属性的主要 属性,colorChanged 回调现在被调用两次:首先由具有默认值的构造函数调用,然后再次从生命周期初始化的某个地方使用空值。

如何避免第二次调用 colorChanged 回调,以便在我未明确提供 binding/value 使用视图的 HTML 标记中的 square 属性?

你将不得不以另一种方式解决这个问题:

import { bindable, autoinject } from "aurelia-framework";

@autoinject
export class SquareCustomAttribute {
  @bindable sideLength;
  @bindable({ primaryProperty: true }) color;

  constructor(private element: Element) {
  }

  sideLengthChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.width = this.element.style.height = newValue;
    }
  }
  
  bind(){
    this.sideLengthChanged(this.sideLength ? this.sideLength : "100px");
    this.colorChanged(this.color ? this.color : "red");
  }

  colorChanged(newValue: string) {
    if (this.element instanceof HTMLElement) {
      this.element.style.backgroundColor = newValue;
    }
  }
}

当你声明{ primaryProperty: true }时,你基本上是在告诉框架在你的自定义属性的值上创建一个绑定,无论它是否被填充,框架都会将它映射到你的颜色属性. 所以当你声明 <div square></div> 时, bind() 生命周期中的颜色 属性 将是一个空字符串。 由于 bind() 只被调用一次,如果它们在开始时为空,它是声明默认值的最佳位置。

此处示例:https://gist.dumber.app/?gist=b0244ac4078e2a0664b7be0fbcc0b22b