1

我正在使用 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 案例中的行为完全相同。有时刷新很顺畅,有时可以看到模板的清空和重新填充。

我可以做些什么来确保模板渲染始终如一的流畅?

4

1 回答 1

0

我遇到了类似的问题 - 这个问题是我在谷歌搜索“arraycontroller flash”时出现的唯一结果。

当我重置阵列控制器的模型时出现问题:

      @set 'model', message

有趣的是,我有一个几乎相同的应用程序,它是使用淘汰赛构建的——并且没有闪烁/刷新问题。

我偶然发现了这篇文章:在 Ember 中刷新内容时缓解闪烁的 UI并最终将我的更新包装在一个 Ember.run 函数中,这解决了闪烁问题,但对我来说仍然是错误的。

      Ember.run =>
        @set 'model', message

[删除完整的红鲱鱼]

到目前为止,正确的路径似乎是包裹在 Ember.run 中 - 丑陋无比,但它确实解决了眼前的问题。我的猜测是 Ember 没有像淘汰赛那样优化/快速,或者 Ember 在更新排队方面存在错误。希望随着时间的推移会有所改善。

编辑 2013 年 7 月 23 日-

写完这篇文章后,我意识到 Ember 是完全正确的,而我是完全错误的。(淘汰赛是偶然的)

如此处所述:http: //emberjs.com/guides/understanding-ember/managing-asynchrony/似乎 Ember 使用事件将更新捆绑在一起 - 在 Ember.run 中有效地包装事件处理程序

但在我的情况下(我认为是你的情况),我们调用的是异步的 ajax 方法。回调(或承诺 - 同样的问题)发生在 Ember 事件触发并返回之后。所以 Ember 无法知道它需要对更新进行排队。

仍然不确定“正确”的解决方案是将其包装在 Ember.run 中 - 文档(http://emberjs.com/api/classes/Ember.run.html)似乎表明它不正确,但文档也推向Ember Data,它不会有这个问题。

猜猜我需要阅读更多关于 Ember 的 runloop 的内容。

于 2013-07-23T03:00:30.477 回答