我有一个只需渲染进度条的简单组件。
初始化很好,进度很好,但模板没有使用新值进行更新。
import {Component} from 'angular2/core';
@Component({
selector : 'progress-bar',
template : `
<div class="progress-container">
<div>{{currentProgress}}</div>
<div [style.width.%]="currentProgress" class="progress"></div>
</div>
`,
styles: [
'.progress-container {width: 100%; height: 5px}',
'.progress {background-color: #8BC34A; height:5px}'
]
})
export class ProgressBar {
currentProgress: number;
constructor() {
this.currentProgress = 0;
}
onProgress(progress: number) {
console.log(progress) //consoles correct percentages
this.currentProgress = progress;
}
reset() {
console.log(this.currentProgress) //is 100
this.currentProgress = 0;
}
}
~
其他地方
ngOnInit() {
this.httpFileService.progress$.subscribe((progress: number) => this.onProgress(progress));
}
onProgress(progress: number) {
this.progressBar.onProgress(progress*100);
}
我觉得我错过了一些非常有用的东西。
答案 0 :(得分:11)
你正在以一种与框架相对立的方式解决这个问题,并且会引起许多人的嚎叫和咬牙切齿。
现在,您手动订阅一个observable - $(document).ready(function(){
$("#{your label id}").toggle(
function(){$("body").css({"overflow": "hidden"});},
function(){$("body").css({"overflow": "auto"});}
);
});
- 然后手动更新子httpFileService.progress$
组件上的属性,绕过angular的更改检测机制 - 这就是UI不是'更新。在设置此属性后,可以 手动触发更改检测,并且UI会按预期更新 - 但同样,您将反对该框架,所以让我们看一下如何使用它:
我认为“其他地方”是您ProgressBar
组件的父级 - 让我们称之为ProgressBar
。
ElsewhereComponent
这里需要注意的最重要的事情是在@Component({
selector: 'elsewhere',
directives: [ProgressBar],
template: `
<div>
<progress-bar [currentProgress]="httpFileService.progress$"></progress-bar>
</div>
`
})
class ElsewhereComponent {
// you can remove the ngOnInit and onProgress functions you posted
// you also don't need a reference to the child ProgressBar component
// ... whatever else you have in this class ...
}
组件上添加了[currentProgress]
:这是告诉角度的,该组件上应该有一个名为progress-bar
的输入属性绑定到currentProgress
。
但是你现在已经撒谎了 - 就像它的情况一样,httpFileService.progress$
根本没有输入,当它试图将这个不存在的属性绑定到给定值时,angular会告诉你它。所以我们需要添加input属性,首选的方法是使用Input()
装饰器:
ProgressBar
这里有两个关键差异需要注意:首先,@Component({
selector : 'progress-bar',
pipes: [AsyncPipe] //import this from angular2/core
template : `
<div class="progress-container">
<div>{{currentProgress | async}}</div>
<div [style.width.%]="currentProgress | async" class="progress"></div>
</div>
`
})
export class ProgressBar {
@Input() currentProgress: Observable<number>;
...
constructor(){
// remove the line you have in here now
}
}
告诉angular @Input()
是一个输入属性。我们还将该属性的类型从currentProgress
更改为number
- 这不是绝对必要的,但它很有用,因为它允许第二个关键区别:
AsyncPipe
已添加到组件的Observable<number>
中,并在其与pipes
的两个模板绑定中使用。这很有用,因为它告诉angular处理订阅Observable的所有脏工作,并在每次发出新值时更新UI。
这就是它所需要的:条形的宽度和它上面的文本现在都会自动更新,以反映从currentProgress
发出的值,而您不必写一行
实现它的命令性代码。