2017-01-01 37 views
1

另一个JavaScript初学者有一个关闭问题......但是,我一直在读封闭绑定(most helpful)上的各种来源,但我仍然无法完全转移到我的具体问题。关闭问题使用d3提示

为了方便,我准备了minimal jsfiddle。我的问题是使用d3-tip与多个不同的渲染逻辑。在jsfiddle中,您可以在顶部和底部看到一个情节。当您将鼠标悬停在框上时,每个图都应该生成自己的工具提示。但是,如您所见,第一个绘图也使用第二个绘图的工具提示回调。或者更一般:最后一个工具提示回调会覆盖以前的回调。

该实现遵循一些标准的d3/d3-tip模式。 Basiscally我有多个绘图功能是这样的:

function somePlottingFunction(data, locator) { 
    var svg = ... // append svg 

    // define plot-specific tooltip logic 
    function tipRenderer(d) { 
    return "Renderer of plot 1: " + d; 
    } 
    tip = d3.tip() 
      .attr("class", "d3-tip") 
      .html(tipRenderer); 
    svg.call(tip); 

    // and a .enter() 
    svg.selectAll("rect") 
     .data(data) 
     .enter() 
     .append("rect") 
     // ... attr ... 
     .on("mouseover", (d) => tip.show(d)) // <= issue here 
     .on("mouseout", (d) => tip.hide(d)); 
} 

代码简单地使用.on("mouseover", tip.show)什么时候工作。然而在我的实际代码中,我需要mouseover中的其他逻辑,这就是为什么我需要一个包装闭包。我的问题是:

  • 为什么封闭关闭了错误的tip变量?或者说:第二个绘图函数如何修改第一个函数的闭包绑定?
  • 体验javascript程序员如何解决这个问题?

注:在的jsfiddle两个绘图函数(和工具提示逻辑)几乎相同,以保持例如小,这表明简单地使用相同的tipRenderer反正。我的实际使用案例是具有完全不同的图的页面,因此,工具提示渲染不能(或不应该)统一。

回答

3

如果您不使用var声明变量,它将变成全局变量。

所以,这是一个简单的修复,这两个函数里面:

var tip = d3.tip() 
    .attr("class", "d3-tip") 
    .direction("s") 
    .html(tipRenderer); 

这里是你的更新提琴:https://jsfiddle.net/wd08acg1/

+0

外卖:学习基础知识_before_高级主题。添加一个问题,以避免我的评论再次被删除:为什么它与普通的'tip.show'虽然工作?我猜是因为在这种情况下'show'函数的'this'绑定了实际的'tip'对象,而在闭包的情况下,由于看到一个全局的JavaScript,javascript不会关闭任何东西。 – bluenote10

+0

我不是在追随你的最后一个问题(“为什么它能够和普通的tip.show一起工作?”),如果你澄清它,我会很感激。但是,请记住,您没有将'this'传递给'tip.show()'(它不适用于箭头函数),而是* datum *。 –

+0

我的意思是用'tip.show'本身替换箭头函数([更新的小提琴](https://jsfiddle.net/vb3xfe5k/6/))。这就是为什么我首先感到困惑。 – bluenote10