简体   繁体   English

使用Dart中的observable进行Angular2变化检测

[英]Using observables in Dart for Angular2 change detection

In my Angular2 app, written in Dart, I have several services that track data shared between components that don't necessarily have any particular relation in the view. 在我用Dart编写的Angular2应用程序中,我有几个服务跟踪组件之间共享的数据,这些服务在视图中不一定有任何特定的关系。 I need updates initiated by any component to be reflected in every component's display, I want the performance benefits of OnPush change detection, I need components to display values that may have been set before the component was created, and I want all of this to be accomplished with minimal boilerplate. 我需要将任何组件发起的更新反映在每个组件的显示中,我想要OnPush更改检测的性能优势,我需要组件来显示在创建组件之前可能已设置的值,并且我希望所有这些都是用最少的样板完成。

My research indicates that Observables might be what I need, but I've been unable to find clear answers on several points. 我的研究表明Observables可能就是我所需要的,但我无法在几个方面找到明确的答案。

Is there an implementation of Observable in Dart that works well with Angular2? Dart中的Observable实现是否适用于Angular2?

Is an Observable meaningfully different from a Dart Stream? 与Dart Stream有明显不同的Observable吗? In particular does an Observable support getting the current value in addition to being notified about future updates? 除了收到有关未来更新的通知之外,Observable还特别支持获取当前值吗?

Last but not least, assuming Observable meets my requirements, what would be the minimal syntax for declaring an Observable String property of a component, initializing it with an Observable retrieved from an injected service, displaying its value in the component's template (starting with a pre-existing value), and having updates to its value automatically mark the component for on push change detection? 最后但并非最不重要的是,假设Observable满足我的要求,那么声明组件的Observable String属性的最小语法是什么,用从注入的服务检索的Observable初始化它,在组件的模板中显示它的值(从pre开始) - 现有值),并且对其值进行更新会自动标记组件以进行推送更改检测吗?

If Observable does not work for this, how else should I do it? 如果Observable对此不起作用,我该怎么办呢? My current idea is using a custom Stream subclass that inserts the most recent value ahead of anything else a new listener receives, and sending that through the async pipe to handle extracting values from the stream and marking for change detection. 我目前的想法是使用自定义Stream子类,它在新侦听器接收的任何其他内容之前插入最新值,并通过async管道发送该子类以处理从流中提取值并标记更改检测。

My ideal solution would look something like this in use: 我理想的解决方案在使用中看起来像这样:

@Injectable()
class MyService {
  @observable int health;
}

@Component(
    ...)
class MyComponent {
  @observable int health;
  MyComponent(MyService service) : health = service.health;
}

And in the template: 在模板中:

<span>{{health | async}}</span>

Or for truly ideal, though this would have to hook into Angular's template compilation somehow (maybe with a transformer? I haven't learned how those work yet): 或者对于真正的理想,虽然这将不得不以某种方式挂钩到Angular的模板编译(可能有一个变换器?我还没有学到它们是如何工作的):

<span>{{health}}</span>

And with just that, it would just work. 只有这样,它才会奏效。

The custom solution I now have working isn't quite as convenient as that, but it's close. 我现在工作的自定义解决方案不是那么方便,但它很接近。

For collections and classes you can use https://pub.dartlang.org/packages/observe . 对于集合和类,您可以使用https://pub.dartlang.org/packages/observe It is not especially designed to be used with Angular2, rather for Polymer <= 0.16.x but it should work well with Angular2 OnPush . 它不是专门设计用于Angular2,而是用于Polymer <= 0.16.x但它应该与Angular2 OnPush

If you make a collection observable 如果你可以观察一个集合

List myList = toObservable([]);

you can subscribe to changes 您可以订阅更改

myList.changes.listen((record) {
  // invoke Angular change detection
});

When classes extend Observable (directly or by applying the Observable mixin) 当类扩展Observable (直接或通过应用Observable mixin)

class Monster extends Unit with Observable {
  @observable int health = 100;

  void damage(int amount) {
    print('$this takes $amount damage!');
    health -= amount;
  }

  toString() => 'Monster with $health hit points';
}

you also can subscribe to changes and notify Angular 您还可以订阅更改并通知Angular

var obj = new Monster();
obj.changes.listen((records) {
  // invoke Angular change detection
});

Note: If you have an observable collection with instances of observable classes, you need to listen to the collection and the containing classes individually. 注意:如果您有一个带有可观察类实例的可观察集合,则需要单独监听集合和包含类。 The collection only reports adds and removals but not property changes of the containing items. 该集合仅报告添加和删除,但不报告包含项目的属性更改。

Is an Observable meaningfully different from a Dart Stream? 与Dart Stream有明显不同的Observable吗? ... ...

I think Dart Observable is meaningful different from a Stream . 我认为Dart ObservableStream有意义不同。 someObservable.changes returns a Stream that emits the changes, but that change events are generated by the Observable implementation and the transformer that generates additional code from the @observable annotations on the properties. someObservable.changes返回一个发出更改的Stream ,但更改事件由Observable实现和变换器生成,该变换器从属性上的@observable注释生成其他代码。

In particular does an Observable support getting the current value in addition to being notified about future updates? 除了收到有关未来更新的通知之外,Observable还特别支持获取当前值吗?

When you bind to the properties of an observable you get the current value. 绑定到observable的属性时,将获得当前值。 When values change and the changes subscription notifies about these changes and you notify Angular change detection that changes have happened, Angular will update the bindings to the recent values. 当值更改并且changes订阅通知有关这些更改并且您通知Angular更改检测已发生更改时,Angular将更新绑定到最近的值。

the minimal syntax for declaring an Observable String property of a component, 声明组件的Observable String属性的最小语法,

The above code example shows an int property but there is no difference when a String is used. 上面的代码示例显示了一个int属性,但使用String时没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM