我想用Aurelia构建一个简单的自定义组件,允许用户输入一个或多个字符串。如果有多个项目,列表应显示列表中每个项目的删除按钮。
我的问题是,当列表中有多个项目时,列表的第一项不会显示删除按钮。 This is how it looks
以下是我对自定义列表组件的代码和html:
查看
<template>
<div repeat.for="item of items">
<input type="text" value.bind="items[$index]">
<button click.delegate="remove($index)"
if.bind="hasMoreThanOne()">Remove</button>
</div>
<button click.delegate="add()">Add</button>
</template>
视图模型
export class List {
items: string[];
constructor() {
this.items = [];
this.add();
}
add() {
this.items.push("");
}
hasMoreThanOne() {
return this.items.length > 1;
}
remove(index) {
this.items.splice(index,1);
}
}
我的问题是双重的:
答案 0 :(得分:10)
Aurelia将任何属于bind
命令的函数视为纯函数。这意味着在传递给函数的参数发生更改之前,它不会再次调用该函数。由于hasMoreThanOne()
的返回值会根据函数的某个参数而变化(当然,因为函数没有任何参数),Aurelia不打算调用再次发挥作用。
当阵列发生变化时Aurelia没有重新评估函数的原因是转发器已经过优化并且发现数组中的第一项没有改变,所以它只是继续使用它所拥有的现有DOM它。使用正确创建的视图,这有助于大大提高性能,但在您的情况下,它会导致不必要的问题。
您通过使用getter找到了一种非最佳方法来处理此问题。这是非最佳的原因是Aurelia默认情况下每隔200ms使用脏检查来检查getter的变化。这解决了您遇到的问题,但不是理想的性能。
考虑到hasMoreThanOne()
函数的简单性,最简单的选择就是简单地内联绑定中的函数,如下所示:
<template>
<div repeat.for="item of items">
<input type="text" value.bind="items[$index]">
<button click.delegate="remove($index)"
if.bind="items.length > 1">Remove</button>
</div>
<button click.delegate="add()">Add</button>
</template>
老实说,我可能会如何处理这个问题。
你也可以像往常一样使用getter,但是将computedFrom
装饰器附加到它上以防止脏检查:
import {computedFrom} from 'aurelia-framework';
export class List {
items: string[];
constructor() {
this.items = [];
this.add();
}
add() {
this.items.push("");
}
@computedFrom('items.length')
get hasMoreThanOne() {
return this.items.length > 1;
}
remove(index) {
this.items.splice(index,1);
}
}
这将为您提供与上面使用的内联绑定完全相同的性能,但还需要编写更多代码。
答案 1 :(得分:1)
如果将cb(canvas.toDataURL("image/png",1));
传递到items.length
中,则每次长度更改时Aurelia都会重新计算该方法。像这样:hasMoreThanOne()
。
在Html中,除非参数已更改,否则Aurelia不会重新赋值功能。
我刚刚使用hasMoreThanOne(items.length)
中的I18n
和function
解决了函数问题。
语言更改后,该功能不会重新评估功能。通过将table
传递给我在boolean
上更改的函数,我解决了它。即使该函数的实际数据没有改变,更改后的布尔值也会触发Aurelia重新评估整个函数。
赞:
event
然后
<td>
${functionToTrigger(item.value, triggerBool}
</td>
答案 2 :(得分:0)
我能用纯粹的运气解决这个问题。将=
函数转换为属性可修复此问题,现在删除按钮也可用于列表中的第一项。
以下是我所做的更改:
hasMoreThanOne()
现在是
hasMoreThanOne() {
return this.items.length > 1;
}
和类似的观点变化:
get hasMoreThanOne() {
return this.items.length > 1;
}
现在是
<button click.delegate="remove($index)"
if.bind="hasMoreThanOne()">Remove</button>
我仍然感到困惑,为什么这改变了什么。所以如果有人能够解释我这种行为,我很高兴听到它。