【问题标题】:Angular2 dart Property binding not updatingAngular2 dart 属性绑定未更新
【发布时间】:2016-08-22 15:44:02
【问题描述】:

你好 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 属性是一个设置器,就像一个事件处理程序。

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”日志消息) - 令人困惑:ngAfterViewInitfunction 的 jb-menu 组件中记录活动断点时,所有当前断点都按预期可见:

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

这会产生:

currentBreakpoints: [small, medium, large, xlarge]

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

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

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

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

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

【问题讨论】:

    标签: angular dart angular-dart angular2-directives


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 首先,非常感谢您的快速回复! :) 好的,我明白了比较参考文献的意义。经过一些测试,我看到 *ngFor 看起来像是使用您提到的第三种方法,因此可以工作。但我不知道,如何使用 IterableDiffers,你有一个小例子吗?我搜索并尝试使用自动完成功能,但使用对我来说毫无意义:D 如果我将 jb-menu 中的设置器更改为普通的公共“变量”,则这些值看起来很完美。但是我必须对这些值做一些检查,所以简单的绑定不是一种选择。 ---在下一条评论中继续---
    • 好的,用.toList()jb-responsive-breakpoints 组件中创建一个新的activeBreakpoints 实例。但我认为这有点hacky,不是吗?也许使用DoCheck 和 ÌterableDiffers' 方法会更高效?
    • 你还在写吗? :D angular.io/docs/ts/latest/api/core/index/DoCheck-class.html 包含一个示例。不确定“公共变量”
    • 我认为如果像currentBreakpoints 这样的数组很小,在每次修改后用toList() 创建一个副本,将是最有效的方法。 (我还是没完全看懂你的代码,只是在数组变化检测的话题上详细阐述)
    • 好的,现在它按预期工作了。 :) 如果您不介意,我将创建一个带有更多解释的答案
    【解决方案2】:

    问题解决了

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

    3 种可能的解决方案(感谢 Günter Zöchbauer):

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

    2. 使用 Stream 来处理单个事件

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-23
      • 2012-07-18
      • 2017-04-28
      • 2011-12-18
      • 2014-04-28
      • 2016-09-23
      • 2015-09-28
      • 1970-01-01
      相关资源
      最近更新 更多