观察对象数组上的属性是否有任何更改
Observe property on an array of objects for any changes
我使用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
数组代替选定的布尔prop
export class ViewModel {
items = [{}, {}, {}];
selectedItems = [];
selectItem(item) {
this.items.push(item);
}
deselectItem(item) {
this.items.splice(this.items.indexOf(item), 1);
}
}
用于绑定目的,使用selectedItems.length
作为您的"any selected"属性
除了Jeremy的例子,您还可以创建一个自定义setter,例如:
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;
}
}
我已经为你创建了一个活塞:http://plnkr.co/edit/OTb2RDLZHf5Fy1bVdCB1?p=preview
这样做,您将永远不会循环查看某些项是否已更改。
我认为您也可以利用EventAggregator
如图所示。这样就不需要一直执行脏检查,而是在自己的VM中处理项目选择事件并发布eventdata;另一边的订阅者将听同样的内容,并执行所需的体操动作。
然而,我从未使用过它,所以我不确定它的更深层次的细节。但是从文档来看,这看起来很简单。
Jeremy让我在这个bug中思考这个问题。看起来你也可以通过一个自定义的绑定行为获得绑定刷新。希望Jeremy能确认我没有做什么太愚蠢的事情。
像这样使用:
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;
}
}
相关文章:
- 为什么不推荐使用“with”?是否有更好或其他方法可以“下降”到对象的命名空间
- 测试对象是否相等和/或对象是否有更多的关键点,但仍然与共同的关键点相等
- javascript中是否有更标准化的方法来转换(序列化)非表单数据以与ajax一起使用
- 我能从“;输入“;事件是否有更好的方法来跟踪文本更改
- AngularJS中的动态表单验证 - 是否有更好的解决方案/方法
- arguments.callee是否仍然可以安全使用,或者是否有更好的选择
- 如何从Node.js运行gullow任务-gullow.start()的任何更好的替代方案
- 是否有更适合从SQL进行筛选的方法
- 优化javascript的任何更好的方法
- 在使用Jest进行测试时,是否有更快的方法重置mock
- JavaScript JSON.任何更有效的方法
- Angular 1.3 中是否有更好的模式,可以在每次修改 ng-repeat 中的项目时调用函数
- 在角度 2 中,是否有更好的方法通过两组引号以外的输入传递字符串
- 组合多个回调的任何更好方法
- 如何为此 jquery 代码使用函数参数,或者是否有更好的解决方案
- 是否有更好的语法来执行此代码
- 如何判断 readStream 是否没有更多要读取的行
- 除了添加调试器之外,是否有更好的方法来调试 MVC3 应用程序中的 javascript
- 检查是否存在更少的文件
- 我正在尝试在大范围内挑选特定单元格中带有“1”的所有行,是否有更有效的方法可以做到这一点