DialogService如下:
.factory("DialogService",function($q,$compile){ return { toast:function(text){ Dialog.toast(text); },alert:function(text){ var deferred = $q.defer(); var d = Dialog.alert(text); d.bind("hide",function(){ deferred.resolve(); }); return deferred.promise; },showModal:function(options){ var dialog = new Dialog(options); dialog.show(function(){ var self = this; if ( "scope" in options ) $compile(self.contentLayer)(options.scope); options.scope.dismiss = function(){ dialog.hide(); } }); if ( "hide" in options ){ dialog.bind("hide",options.hide); } },...
我面临的问题是,每次创建新模态时,它都会在使用指令时使用新观察者来调整范围.
我通过添加观察者来解决大部分问题,这些观察者在我的自定义指令中销毁节点时删除了观察者,但ng-repeat,ng-if等等……在模态内容中,每次调用showModal时都会添加观察者.
现在,我甚至不确定应该尝试什么方法.
现在我试图删除用对话框创建的观察者,但我没有成功,所以我将不胜感激任何帮助.
解决方法
首先,不是直接将范围传递给对话框服务,如问题所示,最好从选项中传递的范围创建子范围.
这样,每次调用$compile来构建模态时,它都不会用监视器和其他东西污染父作用域,并且当模态关闭时很容易破坏新创建的作用域.
angular.module("app",[]) .factory("DialogService",showModal:function(options){ var childScope; var dialog = new Dialog(options); dialog.show(function(){ var self = this; if ( "scope" in options ){ var childScope = options.scope.$new(); $compile(self.contentLayer)(childScope); options.scope.dismiss = function(){ dialog.hide(); } dialog.bind("hide",function(){ childScope.$destroy(); }); } }); if ( "hide" in options ){ dialog.bind("hide",options.hide); } },confirm:function(text){ var deferred = $q.defer(); Dialog.confirm(text,function(){ deferred.resolve(); },function(){ deferred.reject(); }); return deferred.promise; } } }) ;
额外
此时,我以为我解决了这个问题,但是通过控制台日志我可以看到每次打开一个新对话框时仍会运行越来越多的摘要周期,尽管这次手表保持不变.
发生的事情是我有很多自定义指令;我非常小心在每个指令的链接函数末尾添加以下行,以避免在上述情况下出现性能问题:
var watchers = [ $scope.$watch(...),$scope.$watch(...),... ]; ... var observer = new MutationObserver(function(mutations) { if (!document.body.contains($element[0])){ observer.disconnect(); dropdown.remove(); for ( var i = 0; i < watchers.length; i++ ){ watchers[i](); } $scope.$destroy(); return; } }); var config = { childList: true,subtree: false /*attributes: true,characterData: true*/ }; observer.observe(document.querySelector('body'),config);
看起来很好,对吗?嗯……大部分时间都有效,但是当我在指令中有这样的东西时(就是这种情况):
var clickHandler = function(event){ var isChild = $($element).has(event.target).length > 0 || $(dropdown).has(event.target).length > 0; var isSelf = $element[0] == event.target || dropdown == event.target; $scope.$apply(function(){ if (!isChild && !isSelf) { $scope.mdselectCtrl.dismiss(); } }); } $document.bind('click',clickHandler);
它是在每个$compile上添加click事件,click事件导致另一个摘要周期(即使范围已经被破坏,此时也不想深入挖掘);考虑到我可以在模态内容中轻松使用相同的指令10-15次,这意味着每次调用$compile都会导致在每次点击时出现大量的摘要周期,从而导致性能下降.
var observer = new MutationObserver(function(mutations) { if (!document.body.contains($element[0])){ observer.disconnect(); dropdown.remove(); for ( var i = 0; i < watchers.length; i++ ){ watchers[i](); } $scope.$destroy(); $document.unbind('click',clickHandler); return; } });
注意
更改对话框服务后,我意识到可能不需要MutationObserver来跟踪节点是否仍然存在,我可以使用:
$scope.$on("destroy")
但我不想让今天更改代码来测试它.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。