我正在使用Aurelia,并且我有一个绑定到网格的项目数组,并且他们有一个选定的属性。我想绑定一个按钮,当任何一个项目为真时启用。我可以通过暴力破解方法来获取筛选列表并返回选定项目的getter,但这意味着我会在应用程序中不断进行脏检查,而且我不想那样做。我希望有一个更有效的方法。有任何想法吗?观察任意变化的对象数组上的属性
回答
,你可以做 - 假设几件事我有你的使用情况的权利:
脏检查(这只是一个财产而不是什么大不了的)
export class Item {
selected = false;
}
export class ViewModel {
items = [new Item(), new Item(), new Item()];
get anySelected() {
var items = this.items, i = items.length;
while(i--) {
if (items[i].selected) {
return true;
}
}
return false;
}
}
观察项目
import {BindingEngine, inject} from 'aurelia-framework';
export class Item {
selected = false;
}
@inject(BindingEngine)
export class ViewModel {
items = [new Item(), new Item(), new Item()];
anySelected = false;
subscriptions = [];
constructor(locator) {
this.bindingEngine = bindingEngine;
}
updateAnySelected() {
var items = this.items, i = items.length;
while(i--) {
if (items[i].selected) {
this.anySelected = true;
return;
}
}
this.anySelected = false;
}
activate() {
var items = this.items, i = items.length, observer;
while(i--) {
observer = this.bindingEngine.propertyObserver(items[i], 'selected');
subscriptions.push(observer.subscribe(() => this.updateAnySelected());
}
this.updateAnySelected();
}
deactivate() {
let dispose;
while(subscription = subscriptions.pop()) {
subscription.dispose();
}
}
}
使用集合类
import {computedFrom} from 'aurelia-framework';
export class Item {
_selected = false;
constructor(parent) {
this.parent = parent;
}
@computedFrom('_selected')
get selected() {
return this._selected;
}
set selected(newValue) {
newValue = !!newValue;
if (newValue === _selected) {
return;
}
_selected = newValue;
this.parent.itemChanged(newValue);
}
}
export class Items {
items = [];
selectedCount = 0;
anySelected = false;
createItem() {
let item = new Item(this);
this.items.push(item);
return item;
}
itemChanged(selected) {
this.selectedCount += (selected ? 1 : -1);
this.anySelected = this.selectCount > 0;
}
}
export class ViewModel {
items = new Items();
constructor() {
let item = this.items.createItem();
item = this.items.createItem();
item = this.items.createItem();
}
}
使用selectedItems
阵列,而不是选择布尔的支撑
export class ViewModel {
items = [{}, {}, {}];
selectedItems = [];
selectItem(item) {
this.items.push(item);
}
deselectItem(item) {
this.items.splice(this.items.indexOf(item), 1);
}
}
结合的目的,使用selectedItems.length
为你的“任何选择”属性
除了杰里米的例子,你可以创建一个自定义二传手,例如:
class Item {
// this is your ~private~ field
_isSelected = false;
// in our constructor, we pass the view model and the property name
constructor(vm, prop, name) {
this.vm = vm;
this.prop = prop;
this.name = name;
}
get isSelected() {
return this._isSelected;
}
// when you set the value, you increase the vm's property
set isSelected(value) {
if (value !== this._isSelected) {
this.vm[this.prop] += value ? 1 : -1;
this._isSelected = value;
}
}
}
export class MyViewModel
{
items = [];
itemsSelected = 0; // that's the property we'll pass to the class we've created
constructor()
{
for (let i = 0; i < 50; i++) {
// instead of adding a annonymous {} here, we add an instance of our class
this.items.push(new Item(this, 'itemsSelected', `Item ${i+1}`));
}
}
toggleIsSelected(item) {
item.isSelected = !item.isSelected;
}
}
我已经创建了一个plunker你:http://plnkr.co/edit/OTb2RDLZHf5Fy1bVdCB1?p=preview
这样做,您将永远不会循环查看某个项目是否已更改。
这与“使用集合类”示例相同,尽管isSelected getter函数中缺少@computedFrom('_ isSelected')装饰器,这意味着isSelected将被脏检查。 –
谢谢你的帮助! –
我想你也可以利用EventAggregator
,如here所示。以这种方式,不需要一直执行脏检查,而是在自己的VM中处理项目选择事件并发布事件数据;另一方的用户将会听到相同的声音并执行所需的体操。
但是,我从来没有使用它,所以我不确定它的更深层的细节。但从文档看起来很容易。
杰里米让我想起了这个in this bug。所以看起来你也可以通过自定义绑定行为来获取绑定刷新。希望杰里米能够证实我在这里没有做任何愚蠢的事情。
像这样来使用:
repeat.for="item of items | filter & array:'propertyName'"
它覆盖标准观察行为,观察你在每个项目定义数组和属性上。它可能可以改进为更通用的...
function observeProperty(obj, property) {
this.standardObserveProperty(obj, property);
let value = obj[property];
if (Array.isArray(value)) {
this.observeArray(value);
for(let each of value){
this.standardObserveProperty(each, this.propertyName);
}
}
}
export class ArrayBindingBehavior {
bind(binding, source, property) {
binding.propertyName = property;
binding.standardObserveProperty = binding.observeProperty;
binding.observeProperty = observeProperty;
}
unbind(binding, source) {
binding.observeProperty = binding.standardObserveProperty;
binding.standardObserveProperty = null;
delete binding.propertyName;
}
}
- 1. 观察属性的变化
- 2. 观察对象的数组的数组的可观察对象
- 3. 在可观察数组中使用可观察属性推送对象仍然会跟踪对象的属性。
- 4. 如何使可观察数组中的对象属性可观察?
- 5. $观察指令的对象属性
- 6. 观察对象图的变化
- 7. Mobx:添加新的(数组)属性到可观察对象
- 8. 访问observable数组中可观察对象的属性 - knockout.js
- 9. WPF:我如何观察观察对象的列表属性
- 10. AngularJS观察工厂对象的属性 - 意外行为
- 11. sproutcore - 观察数组项目的属性
- 12. 观察对象数组中每个对象的特定属性 - 角度素材
- 13. KnockoutJS如何观察对象属性?
- 14. 无法观察属性[]对象
- 15. 作为对象属性后,可观察数组asp.net mvc
- 16. knockout使用'观察'为某些属性映射对象数组
- 17. Vue - 组件道具不能正确观察对象的变化
- 18. knockoutjs可观察对象的可观察数组绑定
- 19. 如何观察模型对象上的所有属性更改?
- 20. 键值观察:我可以观察所有属性的变化吗?
- 21. 组合可观察对象
- 22. 如何NSObject的性质观察变化
- 23. Aurelia路上观察到与对象属性
- 24. EmberJS,如何观察一个哈希的任何对象的变化
- 25. KVO - 观察NSArray中包含的对象的属性
- 26. 观察UIDatePicker中的变化
- 27. 观察MySQL的变化表?
- 28. 耙 - 观察变化
- 29. GreenDAO:观察变化
- 30. KnockoutJS可观察对象的可观察对象
太棒了!一些很棒的选择。谢谢。 –
这个改变了吗? –
是的......这有改变吗? – Reft