我有一个Angular.js指令,可以呈现一些D3图表:
angular.module('my-app.deltaChart', [])
.directive('deltaChart',
[ function() {
return {
restrict : 'E',
scope : {
data : '='
},
link : function(scope, element) {
var container = element[0];
var svg = d3.select(container)
.append("svg");
var render = function(data) {
if (!data) {
return;
}
var bars = svg.selectAll("g");
/**
etc...
**/
}
scope.$watch("data", function(newData) {
render(newData);
}, true);
render(scope.data);
}}}]);
我在代码中不止一次使用此指令:
<div class="col-md-4">
<delta-chart data="currentData.values"></delta-chart>
</div>
<div class="col-md-4">
<delta-chart data="pastData.values"></delta-chart>
</div>
DOM中的用户操作可以通过ng-click
函数更改currentData.values和pastData.values的内容。但是,只有DOM中指定的最后一个图表会更新以反映新数据;其他render
函数不会被调用。
我最终跟踪了这个奇怪的行为,直到render
函数表现得像一个全局变量。我的印象是,在指令的link
函数中声明的任何变量都是本地范围的,并且在声明指令的任何时候都会实例化。但是,render
函数似乎表现得像一个全局变量。将它绑定到指令的scope
解决了问题:
scope.render = function(data) {
...
}
scope.$watch("data", function(newData) {
scope.render(newData);
}, true);
即使使用两种不同类型的指令(D3中的渲染图表),这也证明了这一点:
<div class="col-md-4">
<delta-chart data="currentData.values"></delta-chart>
</div>
<div class="col-md-4">
<ring-chart data="otherData.values"></ring-chart>
</div>
如果两者都有一个名为render
的函数,则只会在变量更新时调用最后声明的函数。
任何人都可以帮我理解Angular.js指令中的变量范围吗?