Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/420.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS:观察维度的最佳方式?_Javascript_Css_Angularjs_Dom_Angularjs Directive - Fatal编程技术网

Javascript AngularJS:观察维度的最佳方式?

Javascript AngularJS:观察维度的最佳方式?,javascript,css,angularjs,dom,angularjs-directive,Javascript,Css,Angularjs,Dom,Angularjs Directive,所以,我想出了一些解决方案,但我仍然不确定什么是最好的。首先作为参考,我可以找到一个类似的问题,尽管它有点老了。这是给以后阅读本文的人的: 目标 我的应用程序中有部分需要响应高度元素。我希望在UI/指令层以最快、最具视觉吸引力的方式实现这一点,而无需显式广播更改事件 选项一:指令 一个简单的指令可以记录每个摘要循环上的维度(并调整事件大小) 问题:变化传播速度不够快,视觉滞后明显 解决方案:使用间隔调用 选项二:$interval 我用$interval调用尝试了同样的方法,但CPU使用率出人

所以,我想出了一些解决方案,但我仍然不确定什么是最好的。首先作为参考,我可以找到一个类似的问题,尽管它有点老了。这是给以后阅读本文的人的:

目标

我的应用程序中有部分需要响应高度元素。我希望在UI/指令层以最快、最具视觉吸引力的方式实现这一点,而无需显式广播更改事件

选项一:指令

一个简单的指令可以记录每个摘要循环上的维度(并调整事件大小)

问题:变化传播速度不够快,视觉滞后明显

解决方案:使用间隔调用


选项二:$interval

我用$interval调用尝试了同样的方法,但CPU使用率出人意料地高,即使在我反转了控制并跟踪了由value监视的简单根集合中的元素之后(避免了指令的多个实例产生的并发计时器)

除了我的环境中一些与GC相关的问题(我目前没有看到任何提示),是否有更好的方法来创建这种流体布局

拟议的解决方案/问题 我的第一个想法是创建一个并发的$digest循环,以有效地监视DOM作为一个整体的任何视觉变化。例如,是否有可能高效地迭代所有计算样式,以生成可由值监视的廉价散列?每次添加和/或更改相关的计算样式时,可以相对便宜地触发的东西

在我构建和分析它之前,有人能评论一下它是否真实,或者首先抽象/重构resize触发器是否更有意义

1.2.9中,关于实现这一目标的首选方法还有其他想法吗

[编辑]另一个可能更简单的问题:是否可以通过Javascript以计算效率高的方式提供1-200ms的实际刷新率?如果是这样,是Angular的$interval,还是“VanillaJS”实现更高效?

请查看


我想这正是你所需要的。你可以观察窗户的宽度等等。我不确定它是否也适用于身高,但你可以扩展它。

不幸的是,这个问题没有得到我想要的那么多关注。。。我没有时间写一个详细的背景说明,剖析器截图等,但我确实找到了一个解决方案,我希望这能帮助其他人处理同样的问题


结论 任何实际的中大型应用程序中的$digest循环都无法处理100ms的刷新

考虑到
setInterval
的要求,我只是完全绕过了循环,而只是在检测到不同维度时才选择广播状态更改(使用
offsetWidth/Height
本机属性)

使用单个
$root
范围清单以100ms的间隔运行,在我的2.4Ghz i7 2013 MBP上使用约10.2%的活动选项卡CPU,这是我所测试过的最好的结果,与使用
$interval
的约84%相比,这是可以接受的

欢迎任何评论和批评,否则,这里是自我包含的指令!显然,您可以创造性地使用范围和/或属性来定制观察者,但为了继续讨论这个主题,我尝试省略任何多余的代码

它将监视一个元素的大小变化,并将其绑定到您选择的一个范围属性,用于具有线性复杂度的N个元素。我不能保证这是实现这一点的最快/最好的方法,但这是我能够快速开发的跟踪状态无关的DOM级别维度更改的最快实现:

app.directive('ngSize', ['$rootScope', function($root) {
  return {
    scope: {
        size: '=ngSize'
    },
    link: function($scope, element, attrs) {

        $root.ngSizeDimensions  = (angular.isArray($root.ngSizeDimensions)) ? $root.ngSizeDimensions : [];
        $root.ngSizeWatch       = (angular.isArray($root.ngSizeWatch)) ? $root.ngSizeWatch : [];

        var handler = function() {
            angular.forEach($root.ngSizeWatch, function(el, i) {
                // Dimensions Not Equal?
                if ($root.ngSizeDimensions[i][0] != el.offsetWidth || $root.ngSizeDimensions[i][1] != el.offsetHeight) {
                    // Update Them
                    $root.ngSizeDimensions[i] = [el.offsetWidth, el.offsetHeight];
                    // Update Scope?
                    $root.$broadcast('size::changed', i);
                }
            });
        };

        // Add Element to Chain?
        var exists = false;
        angular.forEach($root.ngSizeWatch, function(el, i) { if (el === element[0]) exists = i });

        // Ok.
        if (exists === false) {
            $root.ngSizeWatch.push(element[0]);
            $root.ngSizeDimensions.push([element[0].offsetWidth, element[0].offsetHeight]);
            exists = $root.ngSizeWatch.length-1;
        }

        // Update Scope?
        $scope.$on('size::changed', function(event, i) {
            // Relevant to the element attached to *this* directive
            if (i === exists) {
                $scope.size = {
                    width: $root.ngSizeDimensions[i][0],
                    height: $root.ngSizeDimensions[i][1]
                };
            }
        });

        // Refresh: 100ms
        if (!window.ngSizeHandler) window.ngSizeHandler = setInterval(handler, 100);

        // Window Resize?
        // angular.element(window).on('resize', handler);

    }
  };
}]);

但是除了基本的响应能力(水平/窗口大小)之外,这并没有做任何事情,坦白地说,仅凭引导和CSS媒体查询就更容易实现。。。我们的目标是实时跟踪动态定位元素的尺寸,并具有最高的计算效率(比如,一组约10-200个节点的渲染组),具有双侦听器(
$watch
window.onresize
),这两者之间是否存在任何并发/循环周期问题?谢谢,很快,这在HTML中是如何使用的?不知道在引用中放什么
app.directive('ngSize', ['$rootScope', function($root) {
  return {
    scope: {
        size: '=ngSize'
    },
    link: function($scope, element, attrs) {

        $root.ngSizeDimensions  = (angular.isArray($root.ngSizeDimensions)) ? $root.ngSizeDimensions : [];
        $root.ngSizeWatch       = (angular.isArray($root.ngSizeWatch)) ? $root.ngSizeWatch : [];

        var handler = function() {
            angular.forEach($root.ngSizeWatch, function(el, i) {
                // Dimensions Not Equal?
                if ($root.ngSizeDimensions[i][0] != el.offsetWidth || $root.ngSizeDimensions[i][1] != el.offsetHeight) {
                    // Update Them
                    $root.ngSizeDimensions[i] = [el.offsetWidth, el.offsetHeight];
                    // Update Scope?
                    $root.$broadcast('size::changed', i);
                }
            });
        };

        // Add Element to Chain?
        var exists = false;
        angular.forEach($root.ngSizeWatch, function(el, i) { if (el === element[0]) exists = i });

        // Ok.
        if (exists === false) {
            $root.ngSizeWatch.push(element[0]);
            $root.ngSizeDimensions.push([element[0].offsetWidth, element[0].offsetHeight]);
            exists = $root.ngSizeWatch.length-1;
        }

        // Update Scope?
        $scope.$on('size::changed', function(event, i) {
            // Relevant to the element attached to *this* directive
            if (i === exists) {
                $scope.size = {
                    width: $root.ngSizeDimensions[i][0],
                    height: $root.ngSizeDimensions[i][1]
                };
            }
        });

        // Refresh: 100ms
        if (!window.ngSizeHandler) window.ngSizeHandler = setInterval(handler, 100);

        // Window Resize?
        // angular.element(window).on('resize', handler);

    }
  };
}]);