如何对Angular2中的可迭代组件属性进行脏检查? [英] How to dirty-check iterable component property in Angular2?

查看:70
本文介绍了如何对Angular2中的可迭代组件属性进行脏检查?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看这个简单的Angular2组件:

Take a look at this simple Angular2 component:

@Component({
  selector: 'status-area',
  directives: [],
  template: require('./status-area.tpl.jade')
})

export class StatusAreaComponent {

  constructor(private _settings: SettingsProvider) {}

  get items() {
     return _.filter(this._settings.features, (feature: any) => {
      return feature.inStatusBar && feature.isEnabled;
    });
  }
}

SettingsProvider 具有属性功能,该属性由另一个组件(例如SettingsPanel)修改.该组件仅通过服务链接(无输入参数).

SettingsProvider has a property features, which is modified by another component (for example SettingsPanel). This components linked only by service (no input params).

因此,如您所见,我只需要从_settings.features属性中获取已启用并标记为与状态栏兼容的功能.

So, as you have seen I need to fetch only enabled and marked as status-bar compatible features from _settings.features property.

为此,我使用lodash方法查找.

For this purpose I use lodash method find.

但是,您可能会猜到,Angular在开发模式下会引发异常:

However, as you might guess, angular throws an exception in development mode:

表达被检查后发生了变化

Expression has changed after it was checked

之所以会这样,是因为每次传递的_.filter()都会返回数组的新实例,但是集合是相同的.

It happens because _.filter() for each pass returns new instance of array, but collection is same.

我的问题是,您如何解决这种情况?或者可能还有其他解决方案/方法来处理这种情况.

My question is, how you solve this situation? Or may be there is another solution/approach to handle this case.

我认为,如果angular2具有这样的特殊装饰器,将非常有用:

In my opinion it would be very useful if angular2 had special decorator like that:

@checkIterable()
get items() {
     return _.filter(this._settings.features, (feature: any) => {
      return feature.inStatusBar && feature.isEnabled;
    });
  }

当然,我可以使用事件和事件侦听器的另一种方法来解决此问题,但是它产生了许多样板代码.

Of course I can solve this by using another approach, with events and events listeners, but it produced a lot of boilerplate code.

看看这个例子:

export class StatusAreaComponent implements OnInit, OnDestroy {

  protected _items;
  protected _removeWatcherFn;

  constructor(private settings: SettingsProvider) {}

  ngOnInit() {
    this._items =  this._fetchItems();

    this._removeWatcherFn = this.settings.onChange.bind(() => {
      this._items =  this._fetchItems();
    });
  }

  ngOnDestroy() {
    this._removeWatcherFn();
  }

  _fetchItems() {
    return _.filter(this.settings.features, (feature: any) => {
      return feature.inStatusBar;
    });
  }


  get items() {
    return this._items;
  }
}

这样Angular很高兴,但我不满意.

In this way Angular is happy, but i don't.

推荐答案

由于您已经在使用lodash,因此可以使用方便的

Since you are already using lodash you can make use of the convenient _.memoize method to cache result of filtering. It is usually used to avoid expensive calculations, but in your case you can benefit from its side-effect because Angular will not have this problem with filtered arrays being different objects for each check.

以下是该问题的可能解决方案:

Here is possible solution for the problem:

@Component({
  selector: 'status-area',
  directives: [],
  template: require('./status-area.tpl.jade')
})
export class StatusAreaComponent {

  constructor(private _settings: SettingsProvider) {
    this.initFilter();
  }

  initFilter() {

    function filterItems(items) {
      return _.filter(items, (feature: any) => {
        return feature.inStatusBar && feature.isEnabled;
      })
    }

    this.filterFeatures = _.memoize(filterItems, function(items) {
      return filterItems(items).map(item => item.id).join();
    });
  }

  get items() {
    return this.filterFeatures(this._settings.features);
  }

}

演示: http://plnkr.co/edit/MuYUO3neJdTs0DHluu0S ?p = info

这篇关于如何对Angular2中的可迭代组件属性进行脏检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆