Angular-bootstrap -反复调用带有bootstrap工具提示的$compile会导致运行缓慢
angular-bootstrap - repeatedly calling $compile with bootstrap tooltip causes slowness
我有一个应用程序设置使用轮询一次,每秒更新饼状图指令。我使用d3来绘制饼状图,我想在饼状图上使用引导工具提示。为了实现这一点,我使用angular-bootstrap,并在每次数据更新时手动调用$compile来处理工具提示指令。它看起来像这样:
app.directive('piechart', ['$compile', function($compile) {
return {
restrict: 'E',
scope: { data: '=', w: '=width', h: '=height', label: '=' },
link: function(scope, element) {
...
var svg = d3.select(element[0])
.append('svg')
.attr('width', scope.w)
.attr('height', scope.h);
scope.$watch('data', function(newValue) {
if (newValue) {
var pieData = pie(newValue);
var arcs = svg.selectAll('g.arc')
.data(pieData, function(d) { return d.data.label; });
arcs.attr('tooltip', function(d, i) {
return scope.data[i].label + ': ' + scope.data[i].value;
}).select('path')
.transition()
.delay(100)
.duration(750)
.attrTween('d', arcTween);
var enteredArcs = arcs.enter()
.append('g')
.attr('class', 'arc')
.attr('transform', 'translate(' + outerRadius + ',' + outerRadius + ')')
.attr('tooltip-append-to-body', true)
.attr('tooltip', function(d, i) {
return scope.data[i].label + ': ' + scope.data[i].value;
});
enteredArcs.append('path')
.attr('fill', 'white')
.attr('stroke', 'white')
.attr('stroke-width', 2)
.on('mouseover', function() { d3.select(this).transition().duration(500).attr('d', arcOver); })
.on('mouseout', function() { d3.select(this).transition().duration(200).attr('d', arc); })
.each(function(d) { this._current = d; }) // store the initial angles
.transition()
.delay(function(d, i) { return (i * 20) + 50; })
.attr('fill', function(d) { return color(d.data.label); })
.attr('d', arc);
arcs.exit().remove();
$compile(svg[0])(scope);
}
}, true);
}
};
}]);
我注意到,在运行了一分钟左右后,它变得非常缓慢和无响应。如果我将鼠标移到元素上进行分析,我看到它在$interpolate.fn
中花费了过多的时间。根据分析器,调用堆栈为:
hideTooltipBind -> Scope。$apply -> Scope。$digest -> $interpolate.fn
(其中hideTooltipBind在ui-bootstrap-tpls.js中)
我猜,在重复调用$compile,旧的工具提示没有清理?这是一个bug在angular引导或问题在我的代码?
编辑:似乎在重复调用$compile时,由第一次调用$compile创建的子范围不会被销毁,而$destroy是取消工具提示绑定的。不知道如何销毁旧的子上下文
我通过在调用$compile之前手动销毁指令作用域的所有子作用域来解决这个问题。因为这个指令使用了一个隔离的作用域,所以应该是安全的。如果谁有更好的主意,我很乐意听听。
代码:var destroyer = function(scopeElem) {
if(scopeElem.$$nextSibling) {
destroyer(scopeElem.$$nextSibling);
}
scopeElem.$destroy();
};
if(scope.$$childHead) {
destroyer(scope.$$childHead);
}
$compile(svg[0])(scope);
相关文章:
- 对iPad上的点击事件反应缓慢
- Ajax请求文档就绪会导致jquery加载缓慢
- Xpath运行缓慢的查询
- 如何使用javascript onmouseover缓慢放大图像
- 错误:[$compile:nonassign]表达式'未定义'与指令'内容可编辑'是不可
- 在什么情况下需要同时使用compile&链接函数的角度
- 具有大型数据集的组件仅在 IE11/Edge 上运行缓慢
- 由于$compile,Javascript(Angular)嵌套指令加载了两次
- Bootstrap在页面加载缓慢时会立即显示隐藏的模式对话框
- 依赖于缓慢加载javascript的UI
- 为什么我用于检查所需输入字段的jQuery脚本如此缓慢
- 如何缓慢移动DOM元素
- 使用.load()-jQuery缓慢加载内容
- 可手持-缓慢粘贴
- Ember 1.10-升级错误-模板必须是一个函数.您是想调用Ember.Handlebars.compile(“..”
- 列表视图在Android上滚动断断续续且缓慢
- nodeJS服务器性能缓慢且不稳定
- bootstrap模式在windowsvista上的IE8上运行极其缓慢
- $compile和ng repeat未返回正确的元素
- Angular-bootstrap -反复调用带有bootstrap工具提示的$compile会导致运行缓慢