AngularJS:看尺寸最好方法? [英] AngularJS: Best way to watch dimensions?

查看:341
本文介绍了AngularJS:看尺寸最好方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我拿出来这几个解决方案,我还不太清楚什么是最好的。首先参考有一个类似的问题,我可以找到,但它是一个有点老了。这是任何人以后阅读本:<一href=\"http://stackoverflow.com/questions/19048985/angularjs-better-way-to-watch-for-height-change\">Watching在角尺寸变化

So, I've come up with a few solutions to this and I'm still not quite sure what is best. First for reference there is one similar question I could find, though it's a bit old. Here it is for anyone reading this later: Watching dimension changes in Angular

目标

我在这是需要高度响应元素我的应用程序的部分。我想最快,最具有视觉吸引力的方式来做到这一点的UI /指令层,而无需显式地播出的变化的事件。

I have portions of my app in which responsive height elements are needed. I want the fastest, most visually appealing way to do this at the UI/directive layer without the need of explicitly broadcasted change events.

方案一:指令

一个简单的指令可以记录每一个消化循环尺寸(和调整事件)

A simple directive can record the dimensions on every digest loop (and resize event)

return {
  scope: {
    size: '=ngSize'
  },
  link: function($scope, element, attrs) {

    var windowEl = angular.element($window),
        handler  = function() {
          if ($scope.size &&
              element.outerWidth() === $scope.size.width &&
              element.outerHeight() === $scope.size.height) return false;
          $scope.size = {
            width: element.outerWidth(),
            height: element.outerHeight()
          };
        };

    windowEl.on('resize', function() {
      $scope.$apply(handler);
    });

    $root.$watch(function() { return [element.outerWidth(), element.outerHeight()] }, handler, true);

  }
};

问题:的变化不会传播速度不够快和视觉滞后是明显的。

Problem: The change doesn't propagate quickly enough and visual lag is noticeable.

解决方案:是一个区间通话

方案二:$间隔

我想同样的事情用$区间通话和它的工作,但是CPU占用高得惊人,即使我倒控制,并保持跟踪元素的单根集合按值看着(避免并发定时器由多个实例制作该指令)。

I tried the same thing with an $interval call and it worked, but CPU usage was surprisingly high, even after I inverted control and kept track of elements in a simple root collection watched by value (avoiding concurrent timers produced by multiple instances of the directive).

除了在我的环境有些GC相关的问题(我没有看到任何表明此当前),可能会有一个更好的方法来创建这种流体布局?

Aside from some GC-related issue in my environment (I don't see anything that suggests this currently), might there be a better approach to creating this kind of fluid layout?

我首先想到的是创建一个并发$消化各种各样的循环,能有效地监控了DOM作为一个整体进行任何视觉上的变化的方法。是否有可能通过有效地计算所有迭代的风格,例如,生产可以由价值观看便宜的哈希?东西,可以相对便宜,每次触发相关的计算样式添加和/或更改?

My first thought would be a way to create a concurrent $digest loop of sorts, to efficiently monitor the DOM as a whole for any visual changes. Is it possible to efficiently iterate through all computed styles, for example, to produce a cheap hash that can be watched by value? Something that can be triggered relatively inexpensively every time a relevant computed style is added and/or changed?

在我建立和配置文件的,至于是否甚至现实,或者如果它只是更有意义抽象/重构的调整大小首先触发?可能有人评论

Before I build and profile it, could someone comment as to whether it's even realistic, or if it simply makes more sense to abstract/refactor the resize triggers in the first place?

在$ P $任何其他的想法pferred方式做到这一点的 1.2.9

Any other ideas on the preferred way to accomplish this in 1.2.9?

的替代,或许更简单的问题:是它甚至有可能通过JavaScript在计算效率的方式提供1-200ms一个现实的刷新率?如果是这样,就这样被角的$间隔,或者可以一个'VanillaJS的实施更有效率?

[edit] An alternate, perhaps simpler question: is it even possible to provide a realistic refresh rate of 1-200ms via Javascript in a computationally-efficient manner? If so, would that way be Angular's $interval, or could a 'VanillaJS' implementation be more efficient?

推荐答案

不幸的是,我本来希望这个问题并没有得到同样的重视......我没有时间来写一个详细的解释与背景,探查截图等,但我没有找到一个解决方案,我希望这可以帮助别人处理了同样的问题。

Unfortunately this question didn't get as much attention as I would have liked... And I don't have time to write a detailed explanation with background, profiler screenshots, etc. But I did find a solution, and I hope this helps someone else dealing with the same issue.

在任何现实中大量应用的消化$循环将无法处理的100毫秒刷新。

The $digest loop in any realistic medium-large application will not be able to handle a refresh of 100ms.

鉴于要求的setInterval 我只是绕过了循环完全,而是选择只播放状态改变时,检测到不同尺寸(使用 offsetWidth /身高本机属性)。

Given the requirement of setInterval I simply bypassed the loop entirely, instead opting to broadcast a state change only when differing dimensions are detected (using the offsetWidth/Height native properties).

在100毫秒的间隔用一个 $根运行范围明显是给任何东西我测试过的最好的结果,对〜10.2%的有源标签我的CPU 2.4GHz的酷睿i7 2013 MBP - 相比与 $间隔的〜84%可以接受

Running at a 100ms interval with a single $root scope manifest is giving the best results of anything I've tested, with ~10.2% active-tab CPU on my 2.4Ghz i7 2013 MBP--acceptable compared to the ~84% with $interval.

任何意见和批评都是欢迎的,否则,这里是自包含的指令!很明显,你可以发挥创意的范围和/或属性自定义的观察家,但停留在话题的兴趣我试图遗漏任何多余的code。

Any comments and critiques are welcome, otherwise, here is the self-contained directive! Obviously you can get creative with the scope and/or attributes to customize the watchers, but in the interest of staying on topic I've tried to omit any superfluous code.

它将监测和放大器;在元素上绑定大小改变你的选择的范围属性,具有线性复杂N个元素。我不能保证它是这样做最快/最好的方式,但它是最快的实现,我可以快速开发出跟踪状态无关的DOM级尺寸的变化:

It will monitor & bind size changes on an element to a scope property of your choosing, for N elements with a linear complexity. I can't guarantee it's the fastest/best way to do this, but it's the fastest implementation I could develop quickly that tracks state-agnostic DOM-level dimension changes:

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);

    }
  };
}]);

这篇关于AngularJS:看尺寸最好方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆