我们在Angular应用程序中使用ng-repeat有很大的渲染峰值。 主页显示了大量的封面图像(“::”和“跟踪”已经到位)。 首次加载时,它可以接受。
但是如果用户更改了状态(我们使用UI-Router)并且之后返回主页,则桌面上的延迟大约为2秒,移动终端则延迟大约10秒。
它应该是即时的:所有json查询都被缓存。并且ng-repeat已经将该内容呈现一次。
作为临时解决方案,我们使用angular ux datagrid(https://github.com/obogo/ux-angularjs-datagrid) 它会立即返回首页,但它不应该在水平模式下工作。使用专用网格来缓存ng-repeat(或者它在场景后面做的事情)似乎有点过分了。
所以问题如下:如何避免ng-repeat重新呈现状态变化内容?
答案 0 :(得分: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及其中的所有内容,只需一次调用即可停用。它会一直静止,直到你重新启用它。