Javascript 角度引导-使用引导工具提示反复调用$compile会导致速度缓慢
我有一个应用程序使用每秒轮询一次来更新饼图指令。我使用d3绘制饼图,我想在饼图上使用引导工具提示。为了实现这一点,我使用angular bootstrap,并在每次数据更新时手动调用$compile来处理tooltip指令。看起来是这样的:Javascript 角度引导-使用引导工具提示反复调用$compile会导致速度缓慢,javascript,angularjs,d3.js,angular-ui-bootstrap,Javascript,Angularjs,D3.js,Angular Ui Bootstrap,我有一个应用程序使用每秒轮询一次来更新饼图指令。我使用d3绘制饼图,我想在饼图上使用引导工具提示。为了实现这一点,我使用angular bootstrap,并在每次数据更新时手动调用$compile来处理tooltip指令。看起来是这样的: app.directive('piechart', ['$compile', function($compile) { return { restrict: 'E', scope: { data: '=', w: '=widt
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引导tpls.js中)
我猜在对$compile的重复调用中,旧的工具提示没有被清理?这是angular bootstrap中的错误还是我的代码中的问题
Edit:似乎在重复调用$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);