d3使用函数参数append()

Ste*_*all 5 javascript d3.js

这有效:

// A
d3.select("body").selectAll(".testDiv")
  .data(["div1", "div2", "div3"])
  .enter().append("div")
    .classed("testDiv", true)
    .text(function(d) { return d; });
Run Code Online (Sandbox Code Playgroud)

以下片段是相同的,除了append的参数,而不是如上所述的"div",是一个函数(d),只返回"div":

// B
d3.select("body").selectAll(".testDiv")
  .data(["div1", "div2", "div3"])
  .enter().append(function(d) { return "div"; })
    .classed("testDiv", true)
   .text(function(d) { return d; });
Run Code Online (Sandbox Code Playgroud)

但是,B不起作用,而是在'Node'上返回错误消息"未捕获的TypeError:无法执行'appendChild':参数1不是'Node'类型."

"div"作为append()的参数function(d) { return "div"; }有何不同?

Dee*_*pak 10

简短的回答是,如果您将append函数作为参数提供,则函数必须返回DOM元素.append方法的文档说明:

该名称可以指定为常量字符串,也可以指定为返回要追加的DOM元素的函数.

以下是使用函数作为参数的append的有效用法:

.append(function() { return document.createElement('div');});
Run Code Online (Sandbox Code Playgroud)

由于下面的代码不返回DOM元素,因此它将被视为无效.

.append(function() { return 'div';});
Run Code Online (Sandbox Code Playgroud)

您的代码无法正常工作的原因从源代码中可以清楚地看出.

  d3_selectionPrototype.append = function(name) {
    name = d3_selection_creator(name);
    return this.select(function() {
      return this.appendChild(name.apply(this, arguments));
    });
  };

  function d3_selection_creator(name) {
    function create() {
      var document = this.ownerDocument, namespace = this.namespaceURI;
      return namespace ? document.createElementNS(namespace, name) : document.createElement(name);
    }
    function createNS() {
      return this.ownerDocument.createElementNS(name.space, name.local);
    }
    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
  }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样typeof name === "function"(在底部附近)是真的,create或者createNS从不调用函数.由于appendChild只接受DOM元素,因此append的函数必须是DOM元素.

  • 替代 document.createElement("div") 的 D3.js 是 d3.creator("div")。这将返回一个用于 .append() 的 html 元素。 (3认同)