我正在使用 Ember.js 构建一个应用程序,该应用程序使用服务器发送事件来添加和更新实现分页的控制器。下面列出了控制器的完整实现。
App.endpointsDisponiblesClass = Ember.ArrayController.extend({
loading: true,
completeList:[
/*
App.Endpoint.create({
id: 1,
id_manufacturer: 1,
id_model: 1,
mac_address: '00:11:22:33:44:55',
last_known_ipv4: '10.0.0.1',
last_scanned: '2012-12-31',
last_configured: null
}),
*/
],
content: [],
offset: null,
limit: 10,
displaySlice: function(offset) {
if (offset >= this.completeList.length)
offset = this.completeList.length - 1;
if (offset < 0) offset = 0;
offset = offset - (offset % this.get('limit'));
if (this.get('offset') == null || offset != this.offset) {
var slice = this.completeList.slice(offset, offset + this.get('limit'));
this.set('offset', offset);
this.set('content', slice);
}
},
displayStart: function() { this.displaySlice(0); },
displayPrevious: function() { this.displaySlice(this.offset - this.limit); },
displayNext: function() { this.displaySlice(this.offset + this.limit); },
displayEnd: function() { this.displaySlice(this.completeList.length); },
startPosition: function() {
return this.get('offset') + 1;
}.property('offset'),
endPosition: function() {
var pos = this.get('offset') + this.get('limit');
if (pos > this.completeList.length)
pos = this.completeList.length;
return pos;
}.property('offset', 'limit'),
displayRefresh: function() {
console.debug('displayRefresh');
var offset = this.get('offset');
this.set('offset', null);
this.displaySlice(offset);
}.observes('completeList.@each')
});
App.endpointsDisponibles = App.endpointsDisponiblesClass.create();
completeList 元素包含我要翻阅的元素的完整列表,其中一个作为注释列出。在我的实现中,我通过将完整列表的切片分配给 ArrayController 子类的“内容”元素来执行分页。此外,还有一些辅助方法可以从显示 Next、Back 等按钮的各种视图中调用。
呈现模型列表的模板片段如下所示:
{{#view tagName="tbody"}}
{{#each App.endpointsDisponibles}}
<tr class="neo-table-data-row">
<td class="neo-table-data-row">{{view Ember.Checkbox checkedBinding="isSelected"}}</td>
<td class="neo-table-data-row">{{mac_address}}</td>
<td class="neo-table-data-row"><a target="_blank" {{bindAttr href="adminUrl"}}>{{last_known_ipv4}}</a></td>
<td class="neo-table-data-row">{{name_manufacturer}}</td>
<td class="neo-table-data-row">{{view Ember.Select
contentBinding="modelSelect"
optionValuePath="content.id_model"
optionLabelPath="content.name_model"
valueBinding="id_model"
disabledBinding="App.endpointScanController.scanInProgress"}}</td>
</tr>
{{else}}
<tr class="neo-table-data-row">
<td class="neo-table-data-row" colspan="7">No endpoints have been discovered or loaded.</td>
</tr>
{{/each}}
{{/view}}
我准备了一个带有 onmessage 处理程序的事件源,该处理程序解析来自服务器的 JSON 消息,并通过在完整列表上添加/更新/删除模型来更新完整列表。由于我使用 displayRefresh() 观察了 completeList.@each,因此如果我查看最后一页并添加了模型,或者删除了查看的模型之一,则页面切片会更新。到目前为止,它运行良好。
问题是消息触发插入的一半时间,模板的重新呈现对用户来说是非常可见的。模板被清空,在大约几分之一秒内保持空白,然后重新填充适当的内容。另一半时间,模板内容可以顺利更新,无需清空和重新填充,这就是我想要的。SSE 消息流是突发的 - 它空闲几秒钟,然后在不到一秒的时间内触发大约 5 到 6 条消息,然后循环重复。在 Firefox 和 Google Chrome 中都观察到了丑陋的渲染。
在 Firefox 中,我安装了 Firebug,我可以从控制台调用控制器方法。当我这样做时,它们的行为与 SSE 案例中的行为完全相同。有时刷新很顺畅,有时可以看到模板的清空和重新填充。
我可以做些什么来确保模板渲染始终如一的流畅?