简体   繁体   English

从d3中的函数内部调用函数

[英]calling functions from within functions in d3

I have what I suspect is a rather basic question on how d3 works. 我怀疑关于d3的工作原理是一个相当基本的问题。 I've started off with this code that works perfectly and triggers the nodeClick actions... 我从这段代码开始,它可以完美地运行并触发nodeClick动作...

var nodeEnter = node.enter()
                        .append("g")
                        .attr("class", "node")
                        .on("click", nodeClick)

But then I changed it to use a function on click to determine whether a single or double click was used... 但是后来我将其更改为使用单击功能来确定是使用单击还是双击...

.on("click", function(d) {
                            if some logic ()  {
                               console.log("double click");
                            } else {
                                console.log("single click only");
                                nodeClick;
                            }
                        })

This works perfectly in terms of outputting the correct console messages, but it seems like my call to nodeClick isn't working properly while embedded within in a function (ie the node click behaviours aren't triggered). 就输出正确的控制台消息而言,这非常有效,但是似乎我对nodeClick的调用在嵌入到函数中时无法正常工作(即,未触发节点点击行为)。 I tried changing to nodeClick() and nodeClick(d) but that just results in errors. 我尝试更改为nodeClick()和nodeClick(d),但这只会导致错误。

Am I missing something that could explain this behaviour? 我是否缺少可以解释这种行为的东西? Seems very strange to me that I'm seeing 2 different behaviours to calling "nodeClick" from outside and inside a function. 我似乎很奇怪,我看到从函数的内部和外部调用“ nodeClick”有两种不同的行为。

Thanks for any help! 谢谢你的帮助!

Here's the complete code in question... 这是有问题的完整代码...

dblclick_timer = false;
//.on("click", nodeClick) //works perfectly
.on("click", function(d) {
    if ( dblclick_timer )  {
        clearTimeout(dblclick_timer)
        dblclick_timer = false
        console.log("double click");
        d.fixed=false;
    }
    else dblclick_timer = setTimeout( function(){
                            dblclick_timer = false
                            console.log("single click only");
                            d3.select(this).nodeClick;
                        }, 250)
})

After all the great feedback, here's the working solution by storing d3.event before it becomes null... 在获得所有宝贵的反馈之后,这是在d3.event变为空之前存储它的有效解决方案...

.on("click", function(d,i) {
                            var cacheEvent = d3.event;
                            if ( dblclick_timer )  {
                                clearTimeout(dblclick_timer)
                                dblclick_timer = false
                                console.log("double click");
                                d.fixed=false;
                                force.start(); 
                            }
                            else dblclick_timer = setTimeout( function(){
                                dblclick_timer = false
                                console.log("single click only");
                                d3.event = cacheEvent;
                                nodeClick.call(d3.select(this), d, i);
                            }, 250)
                        })

As stated in the first comment, you have to establish the correct context: it's a javaScript thing, not a d3 thing. 如第一条评论所述,您必须建立正确的上下文:这是javaScript,而不是d3。 If you establish the correct this context and pass the same parameters it will work exactly the same. 如果您树立正确this背景下,并通过相同的参数,将工作完全一样。 The key is to use Function.prototype.call to invoke the callback. 关键是使用Function.prototype.call来调用回调。 This is standard javaScript . 这是标准的javaScript

.on("click", function(d, i) {
                            if some logic ()  {
                               console.log("double click");
                            } else {
                                console.log("single click only");
                                nodeClick.call(this, d, i);
                            }
                        })  

As stated in the documents 文件所述

The specified listener is invoked in the same manner as other operator functions, being passed the current datum d and index i, with the this context as the current DOM element. 以与其他运算符功能相同的方式调用指定的侦听器,将其传递给当前数据d和索引i,并将此上下文作为当前DOM元素。

As pointed out in the comments, you're not actually calling the function. 正如注释中指出的那样,您实际上并不是在调用该函数。 In the case 在这种情况下

.on("click", nodeClick)

the function nodeClick() is installed as the handler for the click event. 功能nodeClick()被安装为click事件的处理程序。 Here nodeClick refers to the function object -- that is, the function itself, not any value it may return for a particular input. 这里的nodeClick指向函数对象-即函数本身,而不是它为特定输入可能返回的任何值。

In the second case, you're doing the same thing, except that you're passing in an anonymous (ie defined on the spot) function rather than a named function. 在第二种情况下,您正在做相同的事情,除了传递的是匿名(即现场定义)函数而不是命名函数。 In both cases, the function will be called when the event occurs. 在这两种情况下,事件发生时都会调用该函数。

The statement nodeClick; 语句nodeClick; on its own has no effect -- it is essentially the same as saying 1; 本身没有效果-基本上与说1;相同1; or foo; foo; where foo is a variable or function defined elsewhere. 其中foo是在其他位置定义的变量或函数。

To make this work, you need to call the function -- add () after the name. 为此,您需要调用函数-名称后添加() In addition, you need to pass any arguments the callback has received -- nodeClick(d) . 另外,您需要传递回调收到的所有参数nodeClick(d) You also need to call it with the same this context as the implementation of the function relies on it. 您还需要使用与this上下文相同的上下文来调用它,因为函数的实现依赖于它。 All of this is done for you if you use selection.each() : 如果您使用selection.each() ,那么所有这些都将为您完成:

d3.select(this).each(nodeClick);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM