Angular 2 中的 ChangeDetectionStrategy.OnPush 和 Observable.subscribe

2024-01-26

我正在尝试结合使用 Observables 时的最佳实践ChangeDetectionStrategy.OnPush.

该示例演示了想要显示某种加载消息(或者可能是简单的旋转动画)的常见场景:

点这里 http://plnkr.co/edit/QhqKigbUi343raXeX21D?p=preview

@Component({
  selector: 'my-app',
  template: `Are we loading?: {{loadingMessage}}`,

  // Obviously "Default" will notice the change in `loadingMessage`...
  // changeDetection: ChangeDetectionStrategy.Default

  // But what is best practice when using OnPush?
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class App implements OnInit {

  private loadingMessage = "Wait for it...";

  constructor() {

  }

  ngOnInit() {

    // Pretend we're loading data from a service.
    // This component is only interested in the call's success
    Observable.of(true)
      .delay(2000)
      .subscribe(success => {

        if(success){
          console.log('Pretend loading: success!');

          // OnPush won't detect this change
          this.loadingMessage = 'Success!';
        }

      });

  }
}

我或多或少理解不变性的要求OnPush而且,至少对我来说,目前在谈论实际模型数据(可能保存在某种商店中)时是有意义的。

所以,我有两个问题:

  1. 为什么不分配新的字符串值'Success!'触发变化检测器?就不变性而言,价值已经改变了,对吗?
  2. 轻量级内部组件应该如何状态(即loadingMessage)使用时实施ChangeDetectionStrategy.OnPush?如果有多种最佳实践,请为我指出正确的方向。

好问题。我有两段萨夫金的话onPush(因为 Angular.io 文档似乎还没有关于此主题的任何信息):

框架将检查OnPush仅当组件的输入发生变化或组件的模板发出事件时。 --ref http://victorsavkin.com/post/133936129316/angular-immutability-and-encapsulation

使用时OnPush,Angular 只会在组件的任何输入属性发生更改、触发事件或可观察对象触发事件时检查组件。 --ref http://victorsavkin.com/post/110170125256/change-detection-in-angular-2(在@vivainio的评论回复中)

第二个引用似乎更完整。 (太糟糕了,它被埋在评论里了!)

为什么不分配新的字符串值Success!触发 改变探测器?就不变性而言,价值已经改变了,对吗?

OnPush不变性是指输入属性,而不是普通实例属性。如果loadingMessage如果输入属性和值发生更改,则会在组件上执行更改检测。 (参见 @Vlado 对 Plunker 的回答。)

轻量级内部组件应该如何状态(即loadingMessage)使用时实施ChangeDetectionStrategy.OnPush?如果有多种最佳实践,请为我指出正确的方向。

到目前为止我所知道的是:

  • If we change the internal state as part of handling an event, or part of an observable firing, change detection executes on the OnPush component (i.e., the view will update). In your particular case, I was surprised that the view did not update. Here are two guesses as to why not:
    • Adding delay()让 Angular 看起来更像是setTimeout()而不是可观察到的变化。setTimeouts 不会导致更改检测执行OnPush成分。在您的示例中,更改检测器已在值之前 2 秒完成其工作loadingMessage被改变了。
    • 就像 @Sasxa 在他的回答中显示的那样,您必须在模板中绑定到Observable。也就是说,也许它不仅仅是“可观察到的火灾”......也许它必须是bound可观察到的火。在这种情况下,创建loadingMessage(或者甚至是更通用的state财产)作为Observable本身将允许您将模板绑定到它的值(或多个异步值),请参阅这个例子 plnkr http://plnkr.co/edit/OiBSDA8Kcsgl4vBF15xW?p=preview.
      2016年4月28日更新:看来绑定必须包括| async,如 plnkr 中所示,并且在这个 plnkr http://plnkr.co/edit/ezpbwhzowWkGQQKgn3FT?p=preview.
  • 如果我们改变内部状态并且它不是事件处理或可观察触发的一部分,我们可以注入ChangeDetectorRef进入我们的组件并调用方法markForCheck()导致更改检测在OnPush组件以及直到根组件的所有祖先组件。如果仅更改视图状态(即组件及其后代的本地状态),detectChanges()可以改为使用,这不会标记所有祖先组件以进行更改检测。Plunker http://plnkr.co/edit/qSENj5Oy3WSfx0O79ouF?p=preview
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular 2 中的 ChangeDetectionStrategy.OnPush 和 Observable.subscribe 的相关文章

  • 邮件附件媒体类型错误 Gmail API

    我正在尝试通过 Javascript 客户端中的 Gmail API 发送带有附加 jpeg 文件的消息 到目前为止我写的代码如下 ajax type POST url https www googleapis com upload gma
  • 访问没有扩展名的静态文件时阻止 Angular 运行

    我有一个用于项目的 Ionic Angular PWA 它还有一个适用于移动设备的本机 Ionic Cordova 应用程序 在应用程序上 我们需要接受与 PWA 具有相同 URL 的深层链接 以便您可以使用相同的链接从 PC 和移动设备进
  • 如何从 URL 字符串中删除某些参数?

    我有这个var存储表示充满参数的 URL 的字符串 我正在使用 AngularJS 我不确定是否有任何有用的模块 或者可能使用纯 JavaScript 来删除不需要的 URL 参数而无需使用正则表达式 例如我需要删除 month 05并且
  • 区分单击与 mousedown/mouseup

    我已经阅读了有关这种情况的 stackoverflow 上的几个答案 但没有一个解决方案有效 我尝试根据用户是否单击某个元素或使用 jQuery 将鼠标按住该元素来执行不同的操作 有可能做到这一点吗 onMouseDown 将在按下左侧或右
  • 从 Angular 11 升级到 Angular 12 后,我的项目未使用优化参数进行编译

    我刚刚升级了环境nrwl https nrwl io 从 Angular 版本 11 到 12 带有两个 Angular 应用程序和多个库 更新后 当我尝试使用优化设置进行编译时 角度 json optimization scripts t
  • 为什么我的 onclick 事件自动触发

    加载页面时最初显示 Hello World 我希望它仅在单击按钮后显示 我知道我可以通过向按钮添加内联事件侦听器来做到这一点 我可以只用脚本编写所有这些代码吗
  • NodeJS 无法加载 css 文件

    所以我正在尝试制作一个 NodeJS 服务器 并且我尝试保留尽可能少的附加组件 但是 我遇到了一个问题 我似乎无法加载任何内容CSS我调用的文件HTML文件 该调用似乎确实由服务器处理 但它不会显示在浏览器中 My 网络服务器 js fil
  • 如何在参数上使用 .reduce() 而不是特定的数组或对象?

    我想定义一个函数 flatten 将多个元素展平为一个数组 我知道以下是不可能的 但本质上我想这样做 var flatten function var flattened arguments reduce function acc elem
  • 如何通过角度2中的父组件将自定义(html)模板传递给子组件?

  • 禁用任何类型的浏览器窗口滚动?

    有没有办法禁用滚动 不仅仅是滚动条 还有浏览器窗口的全部功能 根据您对 Keit 的回答 您不想在打开灯箱时滚动处于活动状态 如果是这种情况 您可以使用以下 css 在打开灯箱的同时向正文添加一个类 这个解决方案的好处是它保留了滚动 空间
  • Rxjs 可观察等待直到满足某些条件

    我有以下重试逻辑来重试操作 对于单个请求来说它工作得很好 对于多个正在进行的请求 我想在重试之前等待现有的重试逻辑完成 handleError errors Observable
  • 如何检查jquery数据表中的每个复选框?

    我有一个第一列带有复选框的表格 我使用 jQuery DataTable 插件显示我的表格 我制作了 2 个链接来选择 取消选择每个复选框 这是选择全部的一个 a href Select all a 和 JavaScript functio
  • Google 地图 v3 中标准缩放控件的样式

    有没有一种简单的方法可以在 Google Maps JavaScript API v3 中设置缩放控件的样式 我想要的只是改变标准图像 http maps gstatic com intl en ALL mapfiles mapcontro
  • 获取 2 个日期之间的月份名称

    我有两个约会from and to 我想获取这两个日期之间的所有月份名称 以下是我的代码 var monthNames January February March April May June July August September
  • Angular AWS Amplify 验证器额外字段

    我正在尝试将 AWS Amplify 与 Angular 结合使用 通过 Cognito 进行身份验证 我面临的问题是 当我调用该组件时
  • 使用 JavaScript 从 URL 变量读取来加载不同的 CSS 样式表

    我试图在我的 WordPress 博客上使用两个不同的样式表 以便在通过 Web 访问页面时使用一个样式表 而在通过我们的 iOS 应用程序访问博客内容时使用另一个样式表 现在 我们将 app true 附加到来自 iOS 应用程序的 UR
  • 地址更改时如何停止 Angular 重新加载

    我正在使用 Angular 的scrollTo and anchorScroll像这样 app controller TestCtrl function scope location anchorScroll scope scrollTo
  • Javascript / jQuery - 转换特殊 html 字符

    我有一个pre元素中包含一些 html 代码 该代码中有特殊字符 例如 lt 所以它不会破坏页面 然后我有一个 javascript 函数 它获取此 pre 元素的内容 突出显示它 使用 codemirror 并用突出显示的文本替换元素内容
  • 从 Node.js 调用 execl、execle、execlp、execv、execvP 或 execvp 的方法

    POSIX 系统公开了一系列exec函数 允许人们将可能不同的东西加载到当前进程中 保留打开的文件描述符 进程标识符等 可以出于多种原因执行此操作 在我的情况下 这是引导 我想更改我自己的进程的命令行选项 然后在现有进程上重新加载它 这样就
  • 使用 stopPropagation() 处理 React 事件委托

    我有一个 React 项目 应该可以放置在任何网站上 我的想法是 我托管一个 javascript 文件 人们放置一个具有特定 ID 的 div 然后 React 在该 div 中进行渲染 到目前为止 除了点击事件之外 这是有效的 这些事件

随机推荐

  • 无法导入数据类模块

    今天我从 apt get 安装了 python 3 7 来尝试新的 dataclasses 模块 我单独安装了它 因为 python3 6 无法升级到 3 7 当我输入 python3 7 version 它给了我 gt gt gt Pyt
  • 代理和 fetchMore()/canFetchMore() 背后的 Qt 模型

    我很想知道当具有增量数据获取的主数据模型位于代理或代理链后面时 视图将如何表现 代理如何进行项目重新排列 例如取消分组代理 示例 http lynxline com jongling qt models http lynxline com
  • 如何在修改后更新 Android 视图?

    我的视图中有一些方法可以修改调用时绘制的一些形状 在 Java 中 为了确保组件已更新 我会调用repaint 有什么可以确保我的视图正确更新吗 我曾在某处读到过这样的呼唤invalidate in the onDraw 方法将使事情保持最
  • HTTP_INTERCEPTORS 仅在 AppModule 中

    我正在尝试在我的 Angular 6 应用程序中实现延迟加载 我所有的 http 调用都是在FeatureModule 延迟加载 但我仍然必须添加HttpClientModule in my AppModule并且不在FeatureModu
  • Node.js 中的 HTTP.request 不断收到错误请求

    我刚刚安装了 Node js 也许我遗漏了一些东西 但我正在尝试一个简单的 http request 但除了 400 个响应之外什么也没有得到 我已经尝试了几个主机但没有运气 我从他们的网站安装了 Node 这不起作用 所以我卸载并通过 H
  • EPPlus:在单元格中定位图像

    我正在尝试使用 Epplus 将图像 插入 Excel 中的单元格 使用以下代码 private static void SetImage ExcelWorksheet sheet ExcelRange cell using WebClie
  • 这个正则表达式是什么意思 - “\p{Lu}”?

    我在 C 中偶然发现了这个正则表达式 我想移植到 javascript 但我不明白以下内容 p Lu p Ll 0 9 当然 我遇到困难的部分是 p Lu 我访问过的所有正则表达式网站都没有提到这个修饰符 任何想法 这些都被考虑Unicod
  • Ruby on Rails - 验证成本

    验证用户输入的成本 价格的最佳方法是什么 验证规则如下 允许的格式示例 23 2 1 23 0 25 5 6 3 小数点后最多两位数 最小值 0 01 最大值 9 99 检查价格并验证格式 rails 3 validates price f
  • MySQL 将 secure-file-priv 设置为多个目录

    有没有办法让MySQL从多个目录加载数据而不需要设置secure file priv 例如 类似 secure file priv path to dir1 path to dir2 从阅读docs https dev mysql com
  • 如何在gridview适配器中回收位图?

    我的 android 应用程序中有一个网格视图 我正在从服务器将图像加载到网格视图 我正在使用延迟加载 我必须回收此处创建的所有位图 如何在适配器或网格视图中执行 Bitmap recycle 我失忆了 请帮助我 您将需要显示一些代码 至少
  • 从 EC2 实例内查找区域

    有没有办法从实例内部查找实例的区域 我正在寻找类似于方法的东西查找实例 ID https stackoverflow com questions 625644 find out the instance id from within an
  • Bash 参数扩展分隔符

    我想得到1 2 3 4 5 6 7 8 9 10使用参数扩展 1 10 和模式匹配 var echo 1 10 echo var 1 2 3 4 5 6 7 8 9 10 有没有一种更优雅的方式 单行 来做到这一点 优雅在于情人眼中 set
  • 是否有针对各种操作系统(和版本)的预处理器定义列表?

    例如的映射 Mac OS 10 6 3 又名 Snow Leopard gt APPLE LP64 Windows 7 Windows XP gt WIN32 Linux gt LINUX 干得好 http predef sourcefor
  • 重新排序 .strings 文件

    In my Localizable Strings我尝试按字母顺序排列所有对 是否可以按字母顺序重新排序我的Localizable strings文件不区分大小写 也许使用 genstring 或特殊的 bash 脚本 例如我有字符串 ap
  • 为什么 Objective-C 实例变量要在接口中声明?

    我刚刚开始接触 Objective C Java 是我的主要面向对象语言 在接口而不是类中定义对象的实例变量似乎很奇怪 我习惯了接口作为公共 API 定义 除了方法签名之外什么都没有 这里不包括常量 是否有某种原因导致状态在接口中定义 即使
  • QGraphicsLineItem::paint() 工件

    我有自己的类 它继承自QGraphicsLineItem并覆盖paint 绘制带箭头的粗线的方法 void MyGraphicsItem paint QPainter aPainter const QStyleOptionGraphicsI
  • 扩展 Swift 中的所有数字类型

    可以说我有这样的东西 extension NSNumber func toLocalCurrency fractDigits Int 2 gt String let formatter NSNumberFormatter formatter
  • Pycharm/IntelliJ IDEA:如何减少代码分隔符的宽度?

    如何让这个竖条变细呢 没有行号的它比有行号的要薄 但对于我的小屏幕来说仍然太胖了 转到文件 gt 设置 gt 编辑器 gt 常规 gt 装订线图标 取消选中该选项Show gutter icons Now the desired appea
  • 打印 WPF FlowDocument

    我正在 WPF 中构建一个演示应用程序 这对我来说是新的 我当前正在 FlowDocument 中显示文本 并且需要打印它 我正在使用的代码如下所示 PrintDialog pd new PrintDialog fd PageHeight
  • Angular 2 中的 ChangeDetectionStrategy.OnPush 和 Observable.subscribe

    我正在尝试结合使用 Observables 时的最佳实践ChangeDetectionStrategy OnPush 该示例演示了想要显示某种加载消息 或者可能是简单的旋转动画 的常见场景 点这里 http plnkr co edit Qh