我的AngularJs应用程序有个大问题.
我从服务器加载HTML内容(自定义表单)。当然,加载的HTML包含一些ng-show、ng-click等.
因此,在我的页面中追加之前,我会对其进行$compile。
效果很好。
但是,每次我$compile加载的HTML时,它都会在我的作用域中添加更多的$$watchers (当然是ng显示观察者)。
下面是一个演示/模拟:http://plnkr.co/edit/6sSazsFAugzE5XmcYkS7
我的问题是:如果在"load some“上单击数百次,$$watchers 不会减少内存泄漏。
我尝试过remove()、empty()、unbind()我的元素(链接),但是$$watchers数组一直在增长,从来没有被清理过。
我怎样才能解决这个问题?我如何清理无用的$$watchers或“未编译”?
谢谢你的帮助!
发布于 2015-03-17 01:01:36
因为新元素是从相同的作用域和相同的元素编译的,所以观察者永远不会被移除。
所有观察者在其作用域被破坏(scope.$destroy())时都会被移除,这在元素被删除时会自动发生。但是您的元素从未被移除,您可以继续用新节点替换它的HTML。
避免这种情况的一个明确方法是避免重新编译每一个新链接,而是生成一个动态的ng-repeat列表。
否则,如果希望保留代码,则可以在每次编译元素时为其创建一个新的作用域。这样,当重新编译它时,以前的作用域就会被销毁,所有的观察者都会被删除。
你可以在这里看到这一点。我所做的就是在编译调用中将scope替换为scope.$new(),以便每次都将新的作用域设置为元素:
http://plnkr.co/edit/PvUAYyb0IUoaT3dVmpGM?p=preview
PS:那是一个有趣的用例,虽然我从来没有遇到过,但它可以为这个角度的社区做出贡献:-)
发布于 2015-06-29 14:50:10
要正确销毁已编译元素的scope,需要执行scope.$destroy()。我建议的解决方案是创建一个继承的范围,然后销毁它:
// if there was already an inherited scope, destroy it properly with $destroy()
if (scope.inheritedScope) scope.inheritedScope.$destroy();
// create new inherited scope every time
scope.inheritedScope = scope.$new(false);
// use it in the compile
$compile(element.contents())(scope.inheritedScope);使用此解决方案的代码分叉:http://plnkr.co/edit/fOOHUGesbHYRiRWeLwKC
仅用element.html替换HTML并只执行scope.$new是不够的。我遇到了一个非常类似的情况,有一个更复杂的指令。一旦被替换,这个指令仍然会产生错误,所以我知道它仍然存在于内存中。
https://stackoverflow.com/questions/29089388
复制相似问题