Javascript Angular2 刷新数组推送视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36247016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2 refreshing view on array push
提问by Omer Kushmaro
I can't seem to get angular2 view to be updated on an array.push function, called upon from a setInterval async operation.
我似乎无法在 array.push 函数上更新 angular2 视图,从 setInterval 异步操作调用。
the code is from this angular plunkr example of setInterval:
代码来自setInterval 的这个angular plunkr 示例:
What i'm trying to do is as follows:
我想要做的是如下:
import {View, Component, bootstrap, Directive, ChangeDetectionStrategy, ChangeDetectorRef} from 'angular2/angular2'
@Component({selector: 'cmp', changeDetection: ChangeDetectionStrategy.OnPush})
@View({template: `Number of ticks: {{numberOfTicks}}`})
class Cmp {
numberOfTicks = [];
constructor(private ref: ChangeDetectorRef) {
setInterval(() => {
this.numberOfTicks.push(3);
this.ref.markForCheck();
}, 1000);
}
}
@Component({
selector: 'app',
changeDetection: ChangeDetectionStrategy.OnPush
})
@View({
template: `
<cmp><cmp>
`,
directives: [Cmp]
})
class App {
}
bootstrap(App);
<!DOCTYPE html>
<html>
<head>
<title>angular2 playground</title>
<script src="https://code.angularjs.org/tools/traceur-runtime.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.js"></script>
<script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.js"></script>
<script data-require="jasmine@*" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.js"></script>
<script src="config.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.37/angular2.min.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<app></app>
</body>
</html>
The above code will work properly if "numberOfTicks" is just a number, (as the plunker original example shows) but once I change it to an array and push data, it won't update.
如果“numberOfTicks”只是一个数字,则上面的代码将正常工作(如plunker原始示例所示),但是一旦我将其更改为数组并推送数据,它就不会更新。
I can't seem to understand why is that.
我似乎无法理解为什么会这样。
The following behaviour is similar to an issue I have when trying to update a graph in angular2 with new data points when using setInterval / setTimeout.
以下行为类似于我在使用 setInterval / setTimeout 时尝试使用新数据点更新 angular2 中的图形时遇到的问题。
Thanks for the help.
谢谢您的帮助。
回答by Thierry Templier
You need to update the whole reference of your array after adding an element in it:
在其中添加元素后,您需要更新数组的整个引用:
constructor(private ref: ChangeDetectorRef) {
setInterval(() => {
this.numberOfTicks.push(3);
this.numberOfTicks = this.numberOfTicks.slice();
this.ref.markForCheck();
}, 1000);
}
}
Edit
编辑
The DoCheck interface could also interest you since it allows you to plug your own change detection algorithm.
DoCheck 接口也可能会让您感兴趣,因为它允许您插入自己的更改检测算法。
See this link for more details:
有关更多详细信息,请参阅此链接:
Here is a sample:
这是一个示例:
@Component({
selector: 'custom-check',
template: `
<ul>
<li *ngFor="#line of logs">{{line}}</li>
</ul>`
})
class CustomCheckComponent implements DoCheck {
@Input() list: any[];
differ: any;
logs = [];
constructor(differs: IterableDiffers) {
this.differ = differs.find([]).create(null);
}
ngDoCheck() {
var changes = this.differ.diff(this.list);
if (changes) {
changes.forEachAddedItem(r => this.logs.push('added ' + r.item));
changes.forEachRemovedItem(r => this.logs.push('removed ' + r.item))
}
}
}
回答by Mark Rajcok
The above code will work properly if "numberOfTicks" is just a number, but once I change it to an array and push data, it won't update. I can't seem to understand why is that.
如果“numberOfTicks”只是一个数字,上面的代码将正常工作,但是一旦我将其更改为数组并推送数据,它就不会更新。我似乎无法理解为什么会这样。
It is because a number is a JavaScript primitive type, and an array is a JavaScript reference type. When Angular change detection runs, it uses ===
to determine if a template binding has changed.
这是因为数字是 JavaScript 原始类型,而数组是 JavaScript 引用类型。当 Angular 更改检测运行时,它用于===
确定模板绑定是否已更改。
If {{numberOfTicks}}
is a primitive type, ===
compares the current and previous values. So the values 0
and 1
are different.
如果{{numberOfTicks}}
是原始类型,则===
比较当前值和先前值。所以值0
和1
是不同的。
If {{numberOfTicks}}
is a reference type, ===
compares the current and previous (reference) values. So if the array reference didn't change, Angular won't detect a change. In your case, using push()
, the array reference isn't changing.
如果{{numberOfTicks}}
是引用类型,则===
比较当前和以前的(引用)值。所以如果数组引用没有改变,Angular 不会检测到变化。在您的情况下,使用push()
,数组引用不会改变。
If you put the following in your template instead
如果您将以下内容放入模板中
<div *ngFor="#tick of numberOfTicks">{{tick}}</div>
then Angular would update the view because there is a binding to each array element, rather then just the array itself. So if a new item is push()
ed, or an existing item is deleted or changed, all of these changes will be detected.
然后 Angular 会更新视图,因为每个数组元素都有一个绑定,而不仅仅是数组本身。因此,如果push()
编辑了新项目,或者删除或更改了现有项目,所有这些更改都将被检测到。
So in your chart plunker, the following should update when the contents of the from
and to
arrays change:
因此,在您的图表 plunker 中,当from
和to
数组的内容更改时,以下内容应更新:
<span *ngFor="#item of from">{{item}}</span>
<span *ngFor="#item of to">{{item}}</span>
Well, it will update if each item is a primitive type.
好吧,如果每个项目都是原始类型,它就会更新。