AngularJS:看尺寸最好方法? [英] AngularJS: Best way to watch dimensions?
问题描述
所以,我拿出来这几个解决方案,我还不太清楚什么是最好的。首先参考有一个类似的问题,我可以找到,但它是一个有点老了。这是任何人以后阅读本:<一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屋!