Angular2用于阵列突变的OnPush变化检测
我有一个data table component()项目,我们将项目从Angular的传统更改检测更改为Angular2用于阵列突变的OnPush变化检测,angular,angular2-changedetection,Angular,Angular2 Changedetection,我有一个data table component()项目,我们将项目从Angular的传统更改检测更改为OnPush,以优化渲染速度 一旦实施了新的更改检测策略,就会出现一个bug,该bug引用了数据对象发生变化时未更新的表,例如对象的属性更新引用:。对于这种类型的需求,例如对大型数据集合(如股票行情器)中单个属性的内联编辑或外部数据更改,可以创建一个强大的用例 为了解决这个问题,我们添加了一个名为trackByProp的定制trackBy属性检查器。参考文献:。不幸的是,这一解决办法没有解决问
OnPush
,以优化渲染速度
一旦实施了新的更改检测策略,就会出现一个bug,该bug引用了数据对象发生变化时未更新的表,例如对象的属性更新引用:。对于这种类型的需求,例如对大型数据集合(如股票行情器)中单个属性的内联编辑或外部数据更改,可以创建一个强大的用例
为了解决这个问题,我们添加了一个名为trackByProp
的定制trackBy属性检查器。参考文献:。不幸的是,这一解决办法没有解决问题
在under live reloading上,您可以看到上面提交中引用的演示正在运行,但在单击触发更改检测之前不会更新表
组件的结构类似于:
表格>正文>行组>行>单元格
所有这些组件都实现了OnPush
。我在行setter中使用getter/setter来触发页面重新计算,如图所示
对于那些实现此模式的人,我们希望继续使用OnPush
更改检测,但是,作为一个具有多个使用者的开源项目,我们可以为屏幕上的可见行值提供某种自定义检查功能
总之,
trackBy
不会触发行单元格值的更改检测,实现这一点的最佳方法是什么?Angular2更改检测不会检查数组或对象的内容
一个很有技巧的解决方法是在变异后创建数组的副本
this.myArray.push(newItem);
this.myArray=this.myArray.slice();
这样This.myArray
引用不同的数组实例,Angular将识别更改
另一种方法是使用IterableDiffer
(用于数组)或keyvaluedifference
(用于对象)
//注入不同的实现
构造函数(不同:KeyValueDifferents){
//存储要与之比较的初始值
this.difference=differences.find({}).create(null);
}
@输入()数据:任意;
ngDoCheck(){
var changes=this.difference.diff(this.data);//检查更改
if(更改和初始化此文件(&T){
//如果发现更改,请执行某些操作
}
}
另请参见您可能希望使用
ChangeDetectorRef
中的markForCheck
方法
我确实有一个类似的问题,我有一个包含大量数据的组件,并且在每个变更检测周期都重新检查它们,这不是一个选项。但是,当我们从URL中查看一些属性并相应地更改视图中的内容时,使用
onPush
我们的视图不会(自动)刷新
因此,在构造函数中,使用DI获取changeDetectorRef
的实例:
构造函数(专用changeDetectorRef:changeDetectorRef)
在需要触发变更检测的任何地方:
this.changeDetectorRef.markForCheck();
我也面临着类似的问题,为了优化我的应用程序性能,我不得不使用changeDetection.OnPush策略。因此,我将它注入到父组件和子组件的构造函数中,changeDetectorRef
export class ChildComponent{
@Input myData: myData[];
constructor(private _cd : ChangeDetectorRef){
}
changeInputVal(){
this.myData = ....something new value with new reference;
this._cd.markForCheck(); // To force angular to trigger its change detection now
}
}
类似地,在子组件中,注入了changeDetectorRef的实例
export class ChildComponent{
@Input myData: myData[];
constructor(private _cd : ChangeDetectorRef){
}
changeInputVal(){
this.myData = ....something new value with new reference;
this._cd.markForCheck(); // To force angular to trigger its change detection now
}
}
每个异步功能都会触发角度变化检测:-
- 任何DOM事件,如单击、提交、鼠标悬停
- 有XHR电话吗
- 任何计时器,如setTimeout()等
obj = { a:'value1', b:'value2'}'
obj.a = value3;
“obj”中“a”的属性值可能已更改,但obj仍指向同一参考,因此此处不会触发角度更改检测(除非您强制触发);
要创建新引用,需要将对象克隆到另一个对象中,并相应地指定其属性
为了进一步理解,请阅读有关不可变数据结构、更改检测的内容,稍后再回答,但另一个解决方法是在变异后使用扩展运算符。。
myArr=[…myArr]
或myObj={…myObj}
这甚至可以在变异时完成:myArr=myMutatingArr([…myArr])
,因为参数作为数组的新引用,使变量采用新引用,因此调用角度检查
如上所述,如果您更改参考,将进行检查,在任何情况下都可以使用spread运算符来精确执行该操作
尽管数据结构中的嵌套数据结构要求将引用更改到嵌套级别,但要小心。您必须进行一次迭代,以返回排列内部的排列,例如:
myObj = {...myObj, propToChange: { ...myObj.propToChange,
nestedPropArr: [ ...myObj.propToChange.nestedPropArr ]
}
}
如果需要对对象等进行迭代,这可能会变得复杂。希望这对别人有帮助 问题应该包括允许重现问题的代码。
ngDoCheck
在我调用类似click的事件之前不会运行。另外,我注意到,*ngFor
中已经有自定义跟踪功能,为什么它无法检测到?我是