在我用 Dart 编写的 Angular2 应用程序中,我有几个服务跟踪在视图中不一定具有任何特定关系的组件之间共享的数据。我需要任何组件启动的更新反映在每个组件的显示中,我想要OnPush更改检测的性能优势,我需要组件显示在创建组件之前可能已经设置的值,并且我希望所有这些都可以完成用最少的样板。
我的研究表明 Observables 可能是我所需要的,但我一直无法在几个方面找到明确的答案。
Dart 中是否有 Observable 的实现与 Angular2 配合良好?
Observable 与 Dart Stream 有什么不同吗?特别是一个 Observable 是否支持获取当前值以及获得有关未来更新的通知?
最后但并非最不重要的是,假设 Observable 满足我的要求,声明组件的 Observable String 属性的最小语法是什么,使用从注入的服务中检索到的 Observable 对其进行初始化,在组件的模板中显示其值(以 pre 开头) -现有值),并且更新其值会自动标记组件以进行推送更改检测?
如果 Observable 对此不起作用,我还应该怎么做?我目前的想法是使用自定义Stream子类,在新侦听器接收到的任何其他值之前插入最新值,并通过async管道发送该值以处理从流中提取值并标记以进行更改检测。
我理想的解决方案在使用中看起来像这样:
@Injectable()
class MyService {
@observable int health;
}
@Component(
...)
class MyComponent {
@observable int health;
MyComponent(MyService service) : health = service.health;
}
Run Code Online (Sandbox Code Playgroud)
在模板中:
<span>{{health | async}}</span>
Run Code Online (Sandbox Code Playgroud)
或者对于真正理想的情况,尽管这必须以某种方式挂钩到 Angular 的模板编译(也许使用转换器?我还没有了解它们是如何工作的):
<span>{{health}}</span>
Run Code Online (Sandbox Code Playgroud)
有了这个,它就会起作用。
我现在使用的自定义解决方案并不像那样方便,但已经很接近了。
我在登录时无法刷新的组件遇到困难.
该组件是navbar.component,其中包含指向我的页面/组件的链接.在它上面,有一个"登录"链接,呈现login.component,我可以在其上提供用户名和密码,然后单击登录按钮.login.component使用user.service,它使用login.component提供的用户名和密码调用后端,存储收到的令牌并重定向到'/'.
此时,应该隐藏navbar.component上的"登录"链接并显示"注销"链接,但在我单击导航栏上的其他链接之前没有任何反应.
2个链接如下:
<a [hidden]="userService.isLoggedIn" [routerLink]="['Login']">Login</a>
<a [hidden]="!userService.isLoggedIn" (click)="userService.logout();" href="javascript:void(0)">Logout</a>
Run Code Online (Sandbox Code Playgroud)
我理解存储令牌并从user.service重定向不会触发更改检测,并且我的属性userService.isLoggedIn不是可观察的,所以我知道我遗漏了一些东西,但不确定该方法是什么/应该是什么.
我已经尝试注入ApplicationRef来调用tick()方法,希望这会触发更改检测,但是失败了.
我应该使我的属性userService.isLoggedIn是一个可观察的吗?
我不确定为什么变化检测在这里不起作用.我尝试过一些东西,包括一个setTimeout.我正在使用RC5.基本上我想根据我的URL中的参数更改内容.应该很简单吧?
thanks.ts
import { Component } from '@angular/core';
import { Card } from '../../components/card/card';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'sd-thanks',
styleUrls: ['thanks.css'],
directives: [Card],
templateUrl: 'thanks.html'
})
export class Thanks {
params: any;
coming: any;
constructor(public route: ActivatedRoute) {
this.params = this.route.params.subscribe(
params => {
this.coming = params['coming'];
console.log(this.coming); // this consoles the correct true/false value
}
);
}
}
Run Code Online (Sandbox Code Playgroud)
thanks.html
<card>
<div *ngIf="coming" class="card-content">
<span class="card-title">We can't wait to see you!</span>
</div>
<div *ngIf="!coming" class="card-content">
<span …Run Code Online (Sandbox Code Playgroud) javascript angular2-routing angular2-changedetection angular
我正在编写一个 angular 2 应用程序,出于性能原因,我尝试在任何地方使用 ChangeDetectionStrategy.OnPush。我有一个需要 OnPush 才能顺利工作的复杂组件,其中包含另一个显示表单的组件(使用 FormBuilder 创建)。我现在注意到,当我点击一个滑块时,它的内部值会更新(即 form.value),但滑块组件不会可视化这个新值,即它卡在旧位置。
我解决这个问题的第一个想法是将叶组件的更改检测策略设置为默认值,但这没有效果,因为显然这也需要更改其父组件的更改检测策略(这在我的应用程序中是不可能的)。
然后我想出了这个主意:
@Component({
...
})
class MyComponent implements OnInit {
constructor(private zone: NgZone) {}
ngOnInit() {
INIT_FORM();
this.form.valueChanges
.subscribe(() => {
this.zone.run(() => {});
});
}
}
Run Code Online (Sandbox Code Playgroud)
但它没有效果。
是否有可能使 angular 2 表单在使用 OnPush 的组件内工作?
我setInterval()在组件类中有一个函数,它每 1/10 秒触发一次。它所做的只是更新一个 d3 图并且不涉及任何角度绑定。
默认情况下setInterval(),从根节点触发角度变化检测。
有没有办法在setInterval()不触发任何更改检测的情况下运行该功能?
我不需要应用程序的其余部分来自我更新,因为我知道这只会影响图表,而 d3 是唯一负责更新图表的人。
问题
Angular 是否旨在不断重新检查所有内容以检测更改?我来自 React 世界,我期待像event triggered -> re-rendering. 我不知道这是来自我的应用程序还是来自 Angular。
如果我有一个从 HTML 模板调用的方法,即使我的组件中没有任何更改,它也会被无限调用。
问题
我有一个类似日历的页面,它加载了大量数据,并且必须在渲染之前进行计算,因为用ngIf指令来做这些事情太困难了。所以我的模板中有如下内容:
<div [innerHTML]="_getDayPrice(item, day) | safeHtml"></div>
Run Code Online (Sandbox Code Playgroud)
如果我在_getDayPrice方法中控制台记录一些东西,它会被无限打印。
我试过的
我已经通过ChangeDetectionRef在我的应用程序中手动注入并执行this.cdRef.detach(). 然而,这感觉很糟糕,因为有时我可能需要重新启用它并再次分离。
我试图调查它是否来自我的父组件应用程序,比如容器。我在我的主 app.component 中渲染了一个 div ,<div class={{computeClass()}}>并在该方法中打印了一个控制台日志,果然它被无限调用。因此,在此之后,我尝试注释掉所有应用程序的服务。如果全部都被注释掉了,它就可以正常工作,但也没有可观察到的数据。我已经调查了大约半天,但没有发现单点故障(比如注释掉这个服务可以解决所有问题)。
使用 chrome 的内置性能选项卡记录性能,但再次从我的代码中找不到任何触发更改的内容。zone.js被反复调用并似乎设置了一个持续发射的间隔。
当然,我已经搜索了服务中的setTimeout和setInterval,但找不到可能导致此问题的不断变化的内容。
结论?
底线是:如果您有一个复杂的 Angular 应用程序并从模板中调用一个方法,以便无限调用该方法,这是否正常?
如果没有,您对可能导致这种情况的原因有任何提示吗?或者有什么其他方法可以绕过它而不是分离 changeRef 检测器?
我唯一关心的是性能。这是一个类似于日历的页面,可以呈现多行,并且在 8GB RAM 的笔记本电脑上严重滞后。我很确定平板电脑或手机几乎会死机。
我已经阅读了几个答案,并且尝试了很多,但是似乎无法解决这个问题。在我的angular 6应用程序中,我尝试打开MatDialog,但收到此错误:
错误错误:
ExpressionChangedAfterItHasBeenCheckedError:
检查表达式后,表达式已更改。上一个值:'@slideDialog:enter'。当前值:“ @ slideDialog:退出”。
当我调试应用程序并单击checkout按钮时,MatDialog将打开,然后在逐步浏览几行后将其关闭。在没有断点的情况下运行应用程序时,您根本看不到对话框打开。
这是模板文件:
<div>
<button id="cancelButton" mat-raised-button (click)="clearCart()">Cancel</button>
<button id="checkoutButton" mat-raised-button color="primary" (click)="openCheckoutDialog(dataSource)" [disabled]="isTableEmpty()">Checkout</button>
</div>
Run Code Online (Sandbox Code Playgroud)
当我单击ID为“ checkoutButton”的按钮时,它将调用 openCheckoutDialog()
这是我的类,其中openCheckoutDialog称为:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-shopping-cart',
templateUrl: './shopping-cart.component.html',
styleUrls: ['./shopping-cart.component.css']
})
export class ShoppingCartComponent implements OnInit {
dataSource: MatTableDataSource<Item>;
itemList: Item[] = [];
constructor(public dialog: MatDialog, private cdr: ChangeDetectorRef) { }
openCheckoutDialog(): void {
const dialogRef = this.dialog.open(ReviewItemListComponent, {
width: '250px',
data: this.itemList
});
// this.cdr.detectChanges();
dialogRef.afterClosed().subscribe(result => {
console.log(`Dialog …Run Code Online (Sandbox Code Playgroud) 我应该始终ChangeDetectionStrategy.OnPush在组件中使用吗?
我总是听到OnPush它绝对令人惊讶,并解决了许多问题,加快了Angular应用的速度,甚至摆脱了NgZone。但是,如果是这样,为什么默认情况下不生成它ng g component?
如果真是太神奇了,那我们应该一直使用它吗?
我在使用 Angular 6 应用程序时遇到问题:
假设我有 2 个组件:父组件和子组件。
孩子有2个输入。当 1 个输入发生变化时,在 ngOnChanges() 中,子组件向父组件发出一些东西。
然后父组件更改子组件的第二个输入。我希望再次调用子组件的更改检测 - 但事实并非如此。子组件的视图显示了第二个输入的旧值。
该申请有以下定义:
为了说明这个案例,我创建了一个简单的演示项目。在那里我不使用商店,所以我没有任何选择器......相反,我使用 rxjs Subject 来使用异步管道。
这里是:
https://angular-ccejq4.stackblitz.io
查看控制台以了解会发生什么以及何时发生。
我已经尝试过的:
我发现新值到达异步管道。然后异步管道调用 markForCheck()。但它不会调用detectChanges()..所以更改检测周期不会运行。视图只会在下一个更改检测周期时正确更改 - 正如您在我的演示应用程序中看到的那样。
有任何想法吗?
谢谢!
rxjs ngrx angular2-changedetection angular angular-changedetection
我正在尝试优化 angular 应用程序中代码的性能。
我知道我可以runOutsideAngular编写一些代码,以免在每个代码运行或事件上引起更改检测。
但是,我runOutsideAngular在使用OnPush变更检测策略时是否需要使用?(对于听众等)