如何将对 d3 元素的引用传递给函数?

How do I pass a reference to a d3 element to function?

我有一个可以通过 "d3.select(this.$el).append('svg')" 操作的元素,我的问题是如何才能在调用的函数中进行相同的操作?

我是 d3 和 jquery 的新手,刚刚完成了 Splunk 的本教程,它同时使用了两者:https://docs.splunk.com/Documentation/Splunk/6.5.3/AdvancedDev/CustomVizTutorial.

当我尝试将 svg 的创建移动到一个单独的函数中时出现问题。这是我的更新视图函数:

    updateView: function(data, config) {
        // Return if no data
        if (!data) {
            return;
        }

        // Assign datum to the data object returned from formatData
        var datum = data;

//START BIT THAT WORKS
        // Clear the div
        /*this.$el.empty();

        // Get color config or use a default yellow shade
        var mainColor = config[this.getPropertyNamespaceInfo().propertyNamespace + 'mainColor'] || '#f7bc38';

        // Set meter max value or use a default
        var maxValue = parseFloat(config[this.getPropertyNamespaceInfo().propertyNamespace + 'maxValue']) || 100;

        // Set height and width
        var height = 220;
        var width = 420;

        // SVG setup
        var svg  = d3.select(this.el).append('svg')
            .attr('width', width)
            .attr('height', height)
            .style('background', 'white')
            .append('g')
            .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

        // Text
        svg.append('text')
            .datum(datum)
            .attr('class', 'meter-center-text')
            .style('text-anchor', 'middle')
            .style('fill', mainColor)
            .text(function(d){
                return "0";
                //return parseFloat(d);
            });*/
//END BIT THAT WORKS

        newFunc=function(myElement) {
            console.log("newFunc");

            // Clear the div
            myElement.empty();

            // Get color config or use a default yellow shade
            mainColor='#f7bc38';

            // Set meter max value or use a default
            maxValue=1000000;

            // Set height and width
            var height = 220;
            var width = 420;

            // SVG setup
            var svg  = d3.select(myElement).append('svg')
                .attr('width', width)
                .attr('height', height)
                .style('background', 'white')
                .append('g')
                .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

            // Text
            svg.append('text')
                .datum(datum)
                .attr('class', 'meter-center-text')
                .style('text-anchor', 'middle')
                .style('fill', mainColor)
                .text(function(d){
                    return "100";
                });
        };
        newFunc(this.$el);
    }

前半部分是教程中的代码,按预期工作(上面已注释掉)。

后半部分是我在一个新函数中复制这段代码,为了简单起见,这里只是一个内部函数。

这会产生错误 "this.ownerDocument is undefined",我已将其缩小为由 "d3.select(myElement).append('svg')" 行引起的错误。

所以我的问题是,传递对该元素的引用并在函数中处理它的正确方法是什么?

简答:你不能。

现在您正在尝试传递一个 jQuery 对象 作为 newFunc 的参数。但是,d3.select 只接受字符串(selector)或 DOM 元素。

根据 D3 API, d3.select:

Selects the first element that matches the specified selector string. If the selector is not a string, instead selects the specified node. (emphases mine)

让我们在第一个片段中看到这一点。 body里面有个<div>,ID是myDiv。如果我们 select 那 div 和 jQuery...

var elem = $("#myDiv");

...您将拥有一个 jQuery 对象。根据 jQuery API:

When creating new elements (or selecting existing ones), jQuery returns the elements in a collection. Many developers new to jQuery assume that this collection is an array. It has a zero-indexed sequence of DOM elements, some familiar array functions, and a .length property, after all. Actually, the jQuery object is more complicated than that. (emphasis mine)

这是片段,看看两个 console.log,比较它们:

var elem = $("#myDiv");
console.log(elem[0]);
console.log(elem);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="myDiv"></div>

如您所见,您不能$(foo)作为参数传递给函数d3.select

不过可以传$(foo)[0],也就是节点。

这是展示这一点的第二个片段。我使用了您的大部分代码,但将 $("#myDiv")[0] 传递给 newFunc:

newFunc = function(myElement) {

  // Get color config or use a default yellow shade
  mainColor = '#f7bc38';

  // Set meter max value or use a default
  maxValue = 1000000;

  // Set height and width
  var height = 220;
  var width = 420;

  // SVG setup
  var svg = d3.select(myElement).append('svg')
    .attr('width', width)
    .attr('height', height)
    .style('background', 'white')
    .append('g')
    .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

  // Text
  svg.append('text')
    .datum("foo")
    .attr('class', 'meter-center-text')
    .style('text-anchor', 'middle')
    .style('fill', mainColor)
    .text(function(d) {
      return "100";
    });
};
var elem = $("#myDiv");
newFunc(elem[0]);
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="myDiv"></div>

PS:由于我们不再有 jQuery 对象,我删除了 myElement.empty();.

PPS:拜托,不要混用D3和jQuery。没有意义。