1

在Angular應用程序中,我們有巨大的ng-repeat渲染尖峯。 主頁顯示封面圖片的巨大列表(「::」和「track by」)。 第一次加載它的作品可以接受。Angular ng-repeat緩存(避免在狀態變化時重新渲染)

但是,如果用戶改變狀態(我們使用UI-Router)並返回主頁,那麼它在桌面上的延遲大約是2秒,移動上的延遲大約是10秒。

它應該是即時的:所有json查詢都被緩存。並且ng-repeat已經呈現了該內容一次。

作爲臨時解決方案,我們使用角度ux數據網格(https://github.com/obogo/ux-angularjs-datagrid) 它使返回到首頁即時,但它不應該工作在水平模式。而使用專用網格來緩存ng-repeat(或者它在場景後面做的事情)看起來有點矯枉過正。

所以問題如下:如何避免在狀態改變時重複渲染內容?

+0

使用緩存的共享服務 – ajmajmajma

+0

緩存什麼?所有的Json都使用$ cacheFactory緩存。問題出在 – AlexParamonov

+0

你壓縮服務器上的圖像嗎?他們多大?你用css調整它們嗎?您可以緩存任何您覺得需要緩存的內容。它說實話聽起來像是和形象的東西,如果你可以做一個小提琴或者其他東西來修飾它,它會很酷。這可以幫助更輕鬆。 – ajmajmajma

回答

2

那麼,如果你禁用了ng-repeat所在範圍的範圍。然後它將不再呈現。它基本上變成靜態內容。這使您可以實際控制渲染時間。

ux-datagrid實際上使用這個概念來關閉dom,它不在視圖之內,所以角度不知道它並且不能渲染它。然後當它在視野中時將其鉤住。

每個作用域都工作在一個摘要循環上。在摘要循環中,它處理作用域中的$觀察者。

如果您刪除那些觀察者,它不消化它或它的孩子。

這些是ux-datagrid在其代碼中使用以激活和停用範圍的兩種方法。您可以將這些複製到另一個對象並將它們用於相同的事物。

/** 
* ###<a name="deactivateScope">deactivateScope</a>### 
* One of the core features to the datagrid's performance is the ability to make only the scopes 
* that are in view to render. This deactivates a scope by removing its $$watchers that angular 
* uses to know that it needs to digest. Thus inactivating the row. We also remove all watchers from 
* child scopes recursively storing them on each child in a separate variable to activate later. 
* They need to be reactivated before being destroyed for proper cleanup. 
* $$childHead and $$nextSibling variables are also updated for angular so that it will not even iterate 
* over a scope that is deactivated. It becomes completely hidden from the digest. 
* @param {Scope} s 
* @param {number} index 
* @returns {boolean} 
*/ 
function deactivateScope(s, index) { 
    // if the scope is not created yet. just skip. 
    if (s && !isActive(s)) { // do not deactivate one that is already deactivated. 
     s.$emit(exports.datagrid.events.ON_BEFORE_ROW_DEACTIVATE); 
     s.$$$watchers = s.$$watchers; 
     s.$$watchers = []; 
     s.$$$listenerCount = s.$$listenerCount; 
     s.$$listenerCount = angular.copy(s.$$$listenerCount); 
     subtractEvents(s, s.$$$listenerCount); 
     if (index >= 0) { 
      s.$$nextSibling = null; 
      s.$$prevSibling = null; 
     } 
     return true; 
    } 
    return false; 
} 

/** 
* ###<a name="activateScope">activateScope</a>### 
* Taking a scope that is deactivated the watchers that it did have are now stored on $$$watchers and 
* can be put back to $$watchers so angular will pick up this scope on a digest. This is done recursively 
* though child scopes as well to activate them. It also updates the linking $$childHead and $$nextSiblings 
* to fully make sure the scope is as if it was before it was deactivated. 
* @param {Scope} s 
* @param {number} index 
* @returns {boolean} 
*/ 
function activateScope(s, index) { 
    if (s && s.$$$watchers) { // do not activate one that is already active. 
     s.$$watchers = s.$$$watchers; 
     delete s.$$$watchers; 
     addEvents(s, s.$$$listenerCount); 
     delete s.$$$listenerCount; 
     if (index >= 0) { 
      s.$$nextSibling = scopes[index + 1]; 
      s.$$prevSibling = scopes[index - 1]; 
      s.$parent = scope; 
     } 
     s.$emit(exports.datagrid.events.ON_AFTER_ROW_ACTIVATE); 
     return true; 
    } 
    return !!(s && !s.$$$watchers); // if it is active or not. 
} 

我不確定這將完全回答你的問題,因爲你使用的是UI-Router。如果視圖被重新創建並且沒有被緩存,那麼它仍然會在編譯時重新渲染它。但是,如果不是這樣,那麼不僅僅只執行一次監視,當您禁用該範圍時,它也會禁用該範圍內的所有子項。基本上從摘要和所有的子節點上分離它。

重新啓用它將它們全部添加回來。所以,您真正關閉了ng-repeat和其中的所有內容,只需一次調用即可停用。在您重新啓用它之前,它會一直靜止下來。

+0

非常感謝,韋斯! – AlexParamonov

+0

經過深入挖掘Angular UI-Router,我發現這個:https://github.com/angular-ui/ui-router/issues/63 這正是我面臨的問題。 Wes的解決方案是好的,如果我只渲染幾個封面,禁用範圍並啓用它之後。 – AlexParamonov

+0

很高興我能幫到你。 –

相關問題