Angular2 dart 属性 绑定不更新
Angular2 dart Property binding not updating
大家好 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 为给定的宽度注册监听器
- 如果 window 的当前宽度超过一个断点,"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(可以用日志消息证明这一点 - 在调整 window 大小时不会调用 "activeBreakpoints changed" 日志消息)
- 令人困惑: 在 ngAfterViewInit
函数的 jb-menu 组件中记录活动断点时,所有当前断点都按预期可见:
@override
ngAfterViewInit() {
_log.finest(
'''
currentBreakpoints: $activeBreakpoints
'''
);
}
这会产生:
currentBreakpoints: [small, medium, large, xlarge]
或更少断点,具体取决于 window 大小。
我可以想象,这是由于两个组件中的列表引用相同。
但我的菜单组件依赖于被调用的 setter - 就像事件处理程序一样。
一些想法如何解决这个问题?
PS: 如果需要更多代码/解释,请询问! :)
(不确定我是否理解你的问题 - 谨慎使用)
Angular2 变化检测只比较对象引用,不比较对象或数组内容。
您可以创建列表的副本 currentBreakpoints = currentBreakpoints.toList()
以使其成为变更检测的不同实例以识别变更。
您可以传递流而不是数组,并使用流发出新值以通知接收器有关更新。如果传递的数组是同一个实例,到这个数组的绑定可能仍然不会更新。
您可以实现DoCheck
并使用IterableDiffers
来检查内容是否在每个变化检测周期发生变化。
问题已解决
所以问题是,如果绑定的引用没有改变,angular 2 不会调用 setter。
3 种可能的解决方案(归功于 Günter Zöchbauer):
每次更改时更改绑定的引用。我将在我的 jb-responsive-breakpoints 组件中使用它,因为它最容易实现并且不应该对小列表造成巨大的性能问题。可以用 eventEmitter.emit(listObject.toList())
而不是 eventEmitter.emit(listObject)
来实现
使用 Stream 来处理单独的事件
- 在组件发射事件之外创建一个 StreamController(以避免输出 属性 只发射一个流事件)
- 将 StreamController 传递给发出事件的组件
- 将附加流传递给组件/所有对来自事件发射组件的事件感兴趣的组件
- 使用该 Stream 来处理个别事件
- 结论:我没用过。它强制您的组件的用户实现此流处理。对于产生许多事件的事件组件可能更好。
- 改为考虑: 下面的 DoCheck 方法
实现DoCheck
接口并使用IterableDiffers
调整angular
的变化检测
- 更多相关信息:angular.io - DoCheck Interface
- 这被 angular 内部使用,例如 *ngFor
大家好 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 为给定的宽度注册监听器
- 如果 window 的当前宽度超过一个断点,"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(可以用日志消息证明这一点 - 在调整 window 大小时不会调用 "activeBreakpoints changed" 日志消息)
- 令人困惑: 在 ngAfterViewInit
函数的 jb-menu 组件中记录活动断点时,所有当前断点都按预期可见:
@override
ngAfterViewInit() {
_log.finest(
'''
currentBreakpoints: $activeBreakpoints
'''
);
}
这会产生:
currentBreakpoints: [small, medium, large, xlarge]
或更少断点,具体取决于 window 大小。
我可以想象,这是由于两个组件中的列表引用相同。
但我的菜单组件依赖于被调用的 setter - 就像事件处理程序一样。
一些想法如何解决这个问题?
PS: 如果需要更多代码/解释,请询问! :)
(不确定我是否理解你的问题 - 谨慎使用)
Angular2 变化检测只比较对象引用,不比较对象或数组内容。
您可以创建列表的副本currentBreakpoints = currentBreakpoints.toList()
以使其成为变更检测的不同实例以识别变更。您可以传递流而不是数组,并使用流发出新值以通知接收器有关更新。如果传递的数组是同一个实例,到这个数组的绑定可能仍然不会更新。
您可以实现
DoCheck
并使用IterableDiffers
来检查内容是否在每个变化检测周期发生变化。
问题已解决
所以问题是,如果绑定的引用没有改变,angular 2 不会调用 setter。
3 种可能的解决方案(归功于 Günter Zöchbauer):
每次更改时更改绑定的引用。我将在我的 jb-responsive-breakpoints 组件中使用它,因为它最容易实现并且不应该对小列表造成巨大的性能问题。可以用
eventEmitter.emit(listObject.toList())
而不是eventEmitter.emit(listObject)
来实现
使用 Stream 来处理单独的事件
- 在组件发射事件之外创建一个 StreamController(以避免输出 属性 只发射一个流事件)
- 将 StreamController 传递给发出事件的组件
- 将附加流传递给组件/所有对来自事件发射组件的事件感兴趣的组件
- 使用该 Stream 来处理个别事件
- 结论:我没用过。它强制您的组件的用户实现此流处理。对于产生许多事件的事件组件可能更好。
- 改为考虑: 下面的 DoCheck 方法
实现
的变化检测DoCheck
接口并使用IterableDiffers
调整angular- 更多相关信息:angular.io - DoCheck Interface
- 这被 angular 内部使用,例如 *ngFor