AngularJS:暂停$digest&;隐藏DOM元素的观察者

AngularJS:暂停$digest&;隐藏DOM元素的观察者,angularjs,optimization,Angularjs,Optimization,我们正在构建一个单页应用程序,其中有多个页面作为选项卡加载。在任何给定的时间,只有一个选项卡的内容是可见的(很像浏览器),因此我们希望暂时暂停$digest,并禁止观察者在隐藏选项卡的那些DOM节点上执行,直到用户切换到该选项卡 是否有一种方法可以实现这一点,以便继续更新背景选项卡的模型,但视图会根据条件进行更新 以下代码说明了该问题: <div ng-repeat="tab in tabs" ng-show="tab.id == current_tab.id"> <!

我们正在构建一个单页应用程序,其中有多个页面作为选项卡加载。在任何给定的时间,只有一个选项卡的内容是可见的(很像浏览器),因此我们希望暂时暂停
$digest
,并禁止观察者在隐藏选项卡的那些DOM节点上执行,直到用户切换到该选项卡

是否有一种方法可以实现这一点,以便继续更新背景选项卡的模型,但视图会根据条件进行更新

以下代码说明了该问题:

<div ng-repeat="tab in tabs" ng-show="tab.id == current_tab.id">
    <!-- tab content with bindings -->
</div>

目标是优化


我已经知道了,但是我想要一个没有Scalyr中包含的额外功能的更具体的解决方案。

好的,我要求您显示一些代码的原因是@Rouby陈述的原因

出于性能目的,您可以使用
ng if
而不是
ng show
ng if
从DOM中删除或恢复元素

<div ng-repeat="tab in tabs" ng-if="tab.id == current_tab.id">
    <!-- tab content with bindings -->
</div>

ng show
在您希望以不同方式设置隐藏样式时很好使用。例如,您可能希望一个隐藏的元素只隐藏其“主体”,而标题仍然显示。使用ng show是可能的,您只需为类定义CSS样式
ng hide


如果要保留$scope的值,可以将这些值与父作用域绑定,父作用域将保持变量不变。

经过一些尝试和错误后,我想出了以下指令,如果属性上的表达式计算为
true
,则暂停所有子级的
$$watchers
,在
false
上,它将恢复所有备份的
$$watchers

app.directive('pauseChildrenWatchersIf', function(){
    return {
        link: function (scope, element, attrs) {

            scope.$watch(attrs.pauseChildrenWatchersIf, function (newVal) {
                if (newVal === undefined) {
                    return;
                }
                if (newVal) {
                    toggleChildrenWatchers(element, true)
                } else {
                    toggleChildrenWatchers(element, false)
                }
            });
            function toggleChildrenWatchers(element, pause) {
                angular.forEach(element.children(), function (childElement) {
                    toggleAllWatchers(angular.element(childElement), pause);
                });
            }

            function toggleAllWatchers(element, pause) {
                var data = element.data();
                if (data.hasOwnProperty('$scope') && data.$scope.hasOwnProperty('$$watchers') && data.$scope.$$watchers) {
                    if (pause) {
                        data._bk_$$watchers = [];
                        $.each(data.$scope.$$watchers, function (i, watcher) {
                            data._bk_$$watchers.push($.extend(true, {}, watcher))
                        });

                        data.$scope.$$watchers = [];
                    } else {
                        if (data.hasOwnProperty('_bk_$$watchers')) {
                            $.each(data._bk_$$watchers, function (i, watcher) {
                                data.$scope.$$watchers.push($.extend(true, {}, watcher))
                            });
                        }
                    }

                }
                toggleChildrenWatchers(element, pause);
            }
        }
    }
});

显示一些代码,如果我们不知道如何隐藏元素,我们将无法提供帮助。我认为这意味着您的架构不好-子模型应该只包含自己的数据,所以您不应该更新隐藏选项卡的模型,所以您可以使用ng if。@DeblatonJean Philippe添加了代码。
ng if
从DOM中删除元素,因此没有监视程序,也没有$digest。@Rouby,但它也会破坏
$scope
,我需要
$scope
保持完整。很抱歉,我之前没有明确说明这一点,但是选项卡中有一些动态创建的子DOM节点也需要保持完整(例如:选项卡中的弹出窗口)以及DOM节点的属性(例如:网格的滚动位置;部分填充的多个输入)。业务规则要求用户完成部分表单填写,然后切换到另一个选项卡,然后返回并完成表单填写。因此,基本上,即使在后台,选项卡也需要保持状态。因此,正如我所说,您可以将这些值存储在父控制器中。您还可以将其存储在特定的服务中。服务是单例的。我正在考虑编写一个类似
ng if
的指令,它不会删除DOM,而是将其临时缓存在某个地方,然后将其替换回来。但更好的方法是保持隐藏的DOM完好无损,只暂时暂停观察者。但选项卡内容包含无法单独使用作用域重建的DOM节点。我看不到比自定义指令更好的方法了:-(@MatjažJurečič是的。为什么:
each(data.$scope.$$watchers,function(i,watcher){data.$bk.$$watchers.push($.extend(true,{},watcher));`
而不仅仅是:data.$bk.$$watchers=data.$scope.$$watchers;