Angular2 dart属性绑定未更新

时间:2016-08-22 15:44:02

标签: angular dart angular-dart angular2-directives

你好Dart和Angular人, 以下问题:

我的app_component.html中有以下模板部分,这是我的app_component.dart自定义组件的模板。

<!-- monitoring active breakpoints-->
<jb-responsive-breakpoints [breakpoints]="breakpoints"
                           [(activeBreakpoints)]="activeBreakpoints">
</jb-responsive-breakpoints>

<!-- using list of active breakpoints -->
<jb-menu [activeBreakpoints]="activeBreakpoints">
    <!--some menu items, irrelevant for this problem-->
</jb-menu>

<!-- testing list of active breakpoints-->
Active Breakpoints:
<ul>
    <li *ngFor="let breakpoint of activeBreakpoints;"> {{breakpoint}}</li>
</ul>

Jb-responsive-breakpoints和jb-menu也是自定义组件。下面的ul测试了jb-responsive-breakpoints的正确功能。

此模板中使用的变量“breakpoints”和“activeBreakpoints”在app_component.dart中定义,代码如下:

//Mapping from window min-width for this breakpoint to label
Map<int, String> breakpoints = {0:'small', 310:'medium', 450:'large', 600:'xlarge'};

List<String> activeBreakpoints = new List<String>();

应该发生什么:

  • jb-responsive-breakpoints为给定宽度注册侦听器
  • 如果窗口的当前宽度超过一个断点,则会更新“activeBreakpoints”列表。此列表包含所有当前活动的断点,例如css允许所有匹配的媒体查询一次处于活动状态
  • 这似乎按预期工作,因为模板中的ul相应更新。

问题:

jb-menu应该获取activeBreakpoints列表以确定何时更改它的外观。 jb-menu上的activeBreakpoints属性是一个setter,就像一个事件处理程序。

jb-menu上的activeBreakpoints属性定义如下:

List<String> _activeBreakpoints;

@Input()
set activeBreakpoints(List<String> breakpoints) {
  _log.finest("ActiveBreakpoints list changed");
  _log.finest("Active Breakpoints: ${breakpoints.fold("", (prevVal, elem) => "$prevVal, $elem")}");
  _activeBreakpoints = breakpoints;
}

get activeBreakpoints {
return _activeBreakpoints;
}

行为:   - 使用空列表调用setter - 因为初始化而是逻辑的   - 不会在进一步的断点更改时调用Setter(可以使用日志消息证明这一点 - 在调整窗口大小时没有“activeBreakpoints changed”日志消息)   - 令人困惑:ngAfterViewInit函数中的jb-menu组件中记录活动断点时,所有当前断点都按预期显示:

@override
ngAfterViewInit() {
  _log.finest(
    '''
    currentBreakpoints: $activeBreakpoints
    '''
  );
}

这会产生:

currentBreakpoints: [small, medium, large, xlarge]

或更少的断点,具体取决于窗口大小。

我可以想象,这是由于两个组件中的列表引用相同。

但是我的菜单组件依赖于被调用的setter - 就像事件处理程序一样。

一些想法如何解决这个问题?

PS:如果需要更多代码/说明,请询问! :)

2 个答案:

答案 0 :(得分:3)

(不确定我是否理解你的问题 - 谨慎使用)

  • Angular2变化检测仅比较对象引用,但不比较对象或数组内容 您可以创建列表currentBreakpoints = currentBreakpoints.toList()的副本,使其成为更改检测的不同实例,以识别更改。

  • 您可以传递流而不是数组,并使用流发出新值以通知接收者有关更新的信息。如果传递的数组是同一个实例,则此数组的绑定可能仍然不会更新。

  • 您可以实施DoCheck并使用IterableDiffers检查每个更改检测周期内容是否已更改。

答案 1 :(得分:2)

问题解决了

所以问题是,如果绑定的引用没有改变,则angular 2不会调用setter。

3种可能的解决方案(GünterZöchbauer的学分):

  1. 在每次更改时更改绑定的引用。我将在我的jb-responsive-breakpoints组件中使用它,因为它是最容易实现的,并且不应该对小列表产生巨大的性能问题。可以使用eventEmitter.emit(listObject.toList())代替eventEmitter.emit(listObject)

  2. 来实施
  3. 使用Stream进行个别事件

    • 在组件发出事件之外创建一个StreamController(以避免仅发出一个流事件的输出属性)
    • 将StreamController传递给发出事件的组件
    • 将附加的流传递给对事件发射组件中的事件感兴趣的组件/所有组件
    • 使用该流进行个别活动
    • 结论:我没有使用它。它会强制组件的用户实现此流处理。对于产生许多事件的事件组件可能更好。
    • 请考虑:下面的DoCheck方法
  4. 实施DoCheck界面并使用IterableDiffers来改变角度的检测

相关问题