我正在使用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. 觀察NSMutableArray對象的計數屬性
- 4. 觀察可變數組中物體屬性的變化
- 5. 在可觀察數組中使用可觀察屬性推送對象仍然會跟蹤對象的屬性。
- 6. 如何使可觀察數組中的對象屬性可觀察?
- 7. AngularJS $ scope。$觀察對象的屬性
- 8. $觀察指令的對象屬性
- 9. 觀察對象圖的變化
- 10. WPF:我如何觀察觀察對象的列表屬性
- 11. 關鍵值觀察 - 如何觀察對象的所有屬性?
- 12. 訪問observable數組中可觀察對象的屬性 - knockout.js
- 13. Mobx:添加新的(數組)屬性到可觀察對象
- 14. 對觀察員的觀察員觀察員是否會發生任何變化?
- 15. AngularJS觀察工廠對象的屬性 - 意外行爲
- 16. sproutcore - 觀察數組項目的屬性
- 17. 觀察對象數組中每個對象的特定屬性 - 角度素材
- 18. KnockoutJS如何觀察對象屬性?
- 19. Ember.js:觀察所有對象屬性
- 20. 無法觀察屬性[]對象
- 21. 作爲對象屬性後,可觀察數組asp.net mvc
- 22. knockout使用'觀察'爲某些屬性映射對象數組
- 23. 打開某些observableArray對象的屬性變成可觀察
- 24. Vue - 組件道具不能正確觀察對象的變化
- 25. knockoutjs可觀察對象的可觀察數組綁定
- 26. 如何觀察模型對象上的所有屬性更改?
- 27. Python - 觀察者模式 - 對象沒有任何屬性
- 28. 如何將數組的可觀察性轉化爲可觀察數組(RxJS)
- 29. 基於可觀察性,從可觀察對象中選擇可觀察對象
- 30. 觀察屬性
太棒了!一些很棒的選擇。謝謝。 –
這個改變了嗎? –
是的......這有改變嗎? – Reft