2013-04-01 22 views
1

我正在使用Ember.js構建一個使用Server-Sent Events添加和更新實現分頁的控制器的應用程序。下面列出了控制器的完整實施。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('[email protected]') 
}); 
App.endpointsDisponibles = App.endpointsDisponiblesClass.create(); 

completeList元素包含我想要翻頁的元素的完整列表,其中一個元素列爲註釋。在我的實現中,我通過將完整列表的切片分配給ArrayController子類的'content'元素來執行分頁。此外,還有一些幫助器方法可以從顯示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}} 

我準備與解析來自服務器的JSON消息的的onmessage處理程序EventSource的,並更新completeList,通過添加/更新/按照completeList的要求去除模型。由於我觀察到每個都帶有displayRefresh()的completeList。@,因此當我查看最後一頁並添加模型或刪除了某個查看模型時,頁面切片會更新。到目前爲止,它完美地工作。

問題是,消息觸發插入的一半時間內,模板的重新呈現對用戶來說是非常明顯的。模板被清空,大約幾分之一秒空着,然後重新填充適當的內容。另一半時間,模板內容順利更新,無需清空和重新填充,這正是我想要的。 SSE消息流是突發性的 - 它閒置幾秒鐘,然後在不到一秒的時間內發出5到6條消息,然後循環重複。在Firefox和谷歌瀏覽器中都觀察到了醜陋的渲染。

在Firefox中,我安裝了Firebug,並且可以從控制檯調用控制器方法。當我這樣做時,他們的行爲與上證所的情況完全相同。有時刷新很平穩,有時可以看到模板的清空和重新填充。

我該怎麼做才能確保模板渲染一直流暢?

回答

0

我有類似的問題 - 這個問題是唯一的結果出現在我的谷歌搜索「陣列控制器閃光燈」。

問題來了,當我重置陣列控制器的型號:

 @set 'model', message 

有趣的是,我已經得到了我使用的淘汰賽建立了一個幾乎相同的應用程序 - 這沒有閃爍/刷新問題。

我偶然發現了這個帖子:Mitigating a flickering UI when refreshing content in Ember,最後把我的更新包裝在Ember.run函數中,這個函數解決了閃爍問題,但它對我來說仍然是錯誤的。

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

[刪除完整的紅鯡魚]

截至目前看來,正確的路徑是在Ember.run包裹 - 醜陋的地獄,但它確實解決眼前的問題。我的猜測是Ember沒有像淘汰賽那樣優化/快速,或者Ember有更新隊列中的錯誤。希望隨着時間的推移它會有所改善。

編輯13年7月23日 -

我意識到以後我寫了這一點,灰燼是完全正確的,我是完全錯誤的。 (和淘汰賽的事情是偶然的)

如下所述:http://emberjs.com/guides/understanding-ember/managing-asynchrony/似乎灰燼使用事件捆綁在一起的更新 - 在Ember.run

但在我的情況下,有效地包裹的事件處理程序(我想你)我們調用一個ajax方法,它是異步的。回調(或承諾 - 同樣的問題)在Ember事件觸發並返回後發生。所以Ember無法知道它需要排隊更新。

仍然不確定「正確」的解決方案是將其包裝在Ember.run中 - 文檔(http://emberjs.com/api/classes/Ember.run.html)似乎表明它不正確,但文檔也推向Ember Data,它不會有這個問題。

猜猜我需要閱讀更多的Ember的runloop。