【问题标题】:Should use ChangeDetectionStrategy.OnPush for eveything?应该对所有事情都使用 ChangeDetectionStrategy.OnPush 吗?
【发布时间】:2018-11-22 08:10:09
【问题描述】:

正如标题所说:我正在从事一个非常大的项目,并且在几个组件中我使用了ChangeDetectionStrategy.OnPush 以避免表现不佳。我想知道,将这种策略放入每个组件中是否“好”,以防万一,在需要时使用ChangeDetectionRef.detectChanges() 以编程方式更新组件?

--

这是我在应用程序中的一个小组件:

 <my-map
    (updatedGeometry)="setUpdatedGeometry($event)"
    [startGraphEdit]="elementToEdit" [startCut]="elementToCut"
    [startCopy]="elementToCopy"
    [updateGraph]="elementToUpdate"
    [showElement]="elementToShow"
    (selectedProfile)="setProfile($event)"
    [reducedChange]="reducedChange"
    (reduceComposer)="setReducedComposer($event)"
    [labelsVisible]="labelsVisible"
    (visibleComposer)="setVisibleComposer($event)"
    [activateLayers]="activeLayers"
    (curLayers)="setCurrentLayers($event)"
    [loadExtent]="extentToLoad"
    (extent)="setExtent($event)"
    [updateZoom]="newZoom"
    (curZoom)="setCurrentZoom($event)"
    (curLon)="setCurrentLon($event)"
    (curLat)="setCurrentLat($event)"
    (poiNotesOffset)="setPoiNotesOffset($event)"
    [cancelPoiNoteCreation]="visibleDetailPanel"
    (poiNoteUpdatedPosition)="setPoiNoteUpdatedPosition($event)"
    [updatePoiNotePosition]="poiNotesElementForUpdate"
    [removePoiNoteElement]="poiNotesElementForDeletion"
    [updatePoiNotes]="updatePoiNotes"
    [projectCode]="prjCode"
    (poiNote)="poiNote($event)"
    [setPrecisionPointerValues]="precisionPointerValues"
    (precisionPointerValues)="updatePrecisionPointer($event)"
    (exploreToolArea)="setExploreToolArea($event)"
    (extentArea)="setExtentArea($event)"
    [exploreToolRadius]="exploreToolRadius"
    (newExploreToolRadius)="setExploreToolRadius($event)"
    [currEnvironment]="currEnvironment"
    (elementSelected)="onElementClick($event)"
    [setaClasses]="classes"
    [height]="mapHeight"
    [width]="mapWidth"
    [offsetX]="mapOffsetX"
    [offsetY]="mapOffsetY"
    [geometriesToHighlight]="geometriesToHighlight"
    [highlightLineElements]="lineElements"
    (poiList)="setPoiList($event)">
  </my-map>

该组件有很多输入和输出,并且还使用SubjectsBehaviorSubjects与其他组件通信。

【问题讨论】:

    标签: angular


    【解决方案1】:

    ChangeDetectionStrategy.OnPush 告诉 Angular 该组件只依赖于它的@Inputs(),并且仅在以下情况下才需要检查:

    输入参考发生变化。

    源自组件或其子组件之一的事件。

    我们明确地运行变更检测。

    因此,这取决于您的组件内容以及您尝试使用它实现的目标。例如,如果您使用async 管道进行订阅,则您的组件不需要ChangeDetectionStrategy.OnPush,因为async 会自动完成这项工作。如果你的组件很大并且使用了大量的数据更改,它应该包含OnPush 策略,因为它会提高你的性能,所以你的整个组件代码不会在每次更改时运行。如果你的组件很小并且只有几个属性和方法,或者它不包含任何订阅或@Input's,或者不做任何经常发生的数据更改,你不需要ChangeDetectionStrategy.OnPush

    【讨论】:

    • 感谢您的回复。我已经编辑了我的答案,以帮助更好地理解我在这个项目中的场景。
    • @JacopoSciampi 如果这是你的小组件,当然你必须添加OnPush策略,否则当你的项目越来越大时,你肯定会遇到性能问题
    • 是的,主容器包含大约 25 个其他带有输入和输出的组件,my-map 就是其中之一。感谢您的帮助。
    【解决方案2】:

    NO NO 和 NO。 Angular 已经为任何代码引入了很多复杂性,但它还为您提供了很多功能,例如变更检测。如果您从 Angular 中删除更改检测,那么您将得到所有坏处而没有好处。如果您的页面中没有数千个组件,那么您将不会注意到在删除更改检测方面有任何明显的改进。

    所以:

    • 始终使用变更检测
    • 在特定情况下分离更改检测,在这些情况下深入检查对象会显着降低性能

    【讨论】:

      【解决方案3】:

      特别是对于非常大的项目,建议使用OnPush 策略来减少更改检测过程,因为这是一项非常昂贵的操作。

      对于继承的项目,建议从叶组件开始应用OnPush 策略并检查一切是否仍在工作。

      仅在这一点上,跟随祖先,一次次上一级到根。最终整体性能将受益。

      Here there is a very good article about change detection in Angular.

      【讨论】:

        猜你喜欢
        • 2020-03-05
        • 2012-10-01
        • 2013-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-04
        相关资源
        最近更新 更多