Jul*_*ian 22 javascript css dom angularjs angularjs-directive
所以,我已经提出了一些解决方案,我仍然不太确定什么是最好的.首先参考我可以找到一个类似的问题,虽然它有点旧.在这里,对于任何阅读此内容的人来说:在Angular中观察尺寸变化
目标
我的应用程序的一部分需要响应高度元素.我想要在UI /指令层执行此操作的最快,最具视觉吸引力的方式,而无需显式广播更改事件.
方案一:指令
一个简单的指令可以记录每个摘要循环的维度(并调整大小事件)
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);
}
};
Run Code Online (Sandbox Code Playgroud)
问题:变化传播不够快,视觉滞后很明显.
解决方案:使用间隔调用
方案二:$ interval
我尝试使用$ interval调用同样的东西并且它工作正常,但CPU使用率却出乎意料地高,即使在我反转控制并跟踪由值监视的简单根集合中的元素之后(避免由指令的多个实例生成的并发计时器) ).
除了我环境中与GC相关的一些问题(我目前没有看到任何暗示这一点),是否有更好的方法来创建这种流畅的布局?
我的第一个想法是创建一个并发的$ digest循环的方法,以有效地监视DOM作为一个整体的任何视觉变化.是否有可能有效地迭代所有计算的样式,例如,生成可以按值观察的廉价哈希?每次添加和/或更改相关的计算样式时,可以相对便宜地触发的东西?
在我构建和分析它之前,有人可以评论它是否真实,或者是否首先抽象/重构调整大小触发器更有意义?
关于在1.2.9中完成此任务的首选方法的任何其他想法?
[编辑] 一个替代的,也许更简单的问题:是否有可能通过Javascript以计算效率的方式提供1-200毫秒的真实刷新率?如果是这样,那会是Angular的$ interval,还是'VanillaJS'实现更有效?
Jul*_*ian 10
不幸的是,我本来希望这个问题并没有得到同样的重视......我没有时间来写背景,探查截图等进行详细的解释,但我没有找到一个解决方案,我希望这有助于别人处理同样的问题.
任何现实的大中型应用程序中的$ digest循环将无法处理100ms的刷新.
鉴于setInterval我要求完全绕过循环,而只是在检测到不同维度时(使用本offsetWidth/Height机属性)选择广播状态更改.
使用单个$root示波器清单以100ms的间隔运行可以获得我测试的任何内容的最佳结果,在我的2.4Ghz i7 2013 MBP上有~10.2%的活动标签CPU - 可接受的比率为~84%$interval.
欢迎任何评论和批评,否则,这是自成一体的指令!显然,您可以使用范围和/或属性来创建自定义观察者,但为了保持主题,我试图省略任何多余的代码.
对于具有线性复杂度的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);
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7829 次 |
| 最近记录: |