D3 console.log 在函数链中
D3 console.log in a function chain
D3 中是否有允许 "in-line" 日志记录的基础 function/object?
我正在阅读 Scott Murry 的精美 D3 书并想这样做:
d3.select("body").selectAll("div")
.log("body")
.data(dataset)
.log("data")
.enter()
.log("enter")
.append("div")
.log("div")
.attr("class", "bar")
.log("class");
我目前正在做这件可怕的事情:
const log = function (msg, val) {
const data = val ? val : this
const label = msg ? msg : "data:"
console.log(label, data)
return data
}
Object.prototype.log = log
这工作正常,产生了这个可点击的控制台输出:
但是.. D3 的方法是什么?
为了在你的链中记录数据,你可以只使用一个假属性:
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("fake", d=> console.log(d));
对于其他事情,我认为没有 "d3" 允许登录的方式,遗憾的是,我认为您必须以正常方式进行:
console.log(d3.select("body").selectAll("div").data(dataset).enter());
您可以通过修改 d3 选择原型来使用您的解决方案(相对于对象原型,我认为这不能被考虑 "horrible" - 尽管我有点偏向于乱用 d3内部),但我觉得您正在寻找 selection.call()
.
如果您想访问当前选择,但不想中断方法链接,selection.call
可能是您最好的选择:
Invokes the specified function exactly once, passing in this selection
along with any optional arguments. Returns this selection. (docs)
被调用函数的第一个参数将是选择,更多的可选参数可以在调用方法本身中传递。一般形式为:
selection.call(func, arg, arg, ...)
function func(selection, arg, arg, ...) {}
使用 selection.call
进行日志记录应该不会太难使用这种方法。这是一个快速模型 (v4/5):
var dataset = d3.range(10);
d3.select("body").selectAll("div")
.call(log,"body")
.data(dataset)
.call(log,"dataset")
.enter()
.call(log,"enter")
.append("div")
.call(log,"div")
.attr("class", "bar")
.call(log,"bar");
function log(sel,msg) {
console.log(msg,sel);
}
结果:
Here's 实际模型。
我首先想到的是 Andrew Reid 在他 making use of selection.call()
. Although that solution is fine, I think it can be improved by directly extending D3's selection. The docs on d3.selection()
中明确提出的方法,即此函数可用于扩展选择原型。
您可以按照以下几行创建自己的记录器:
const logger = {
log() {
console.log(...arguments);
return this;
}
}
这可以很容易地混入d3.selection.prototype
:
Object.assign(d3.selection.prototype, logger);
简单方法 logger.log()
只是记录所有传递给控制台调用的参数,并通过返回 this
来促进方法链接,它指的是选择本身。
当然,可以很容易地想象出许多更有用的日志记录方法,用于打印属性、选择、数据等等。以下演示扩展了基本概念:
const logger = {
log() { // Generic method logging all arguments.
console.log(...arguments);
return this;
},
logMsg(msg) { // Logging just a simple msg.
console.log(msg);
return this;
},
logSel() { // Log the selection.
console.log(this);
return this;
},
logAttr(name) { // Log the attributes with "name" for all selected elements.
this.each(function(d, i) {
let attr = d3.select(this).attr(name);
console.log(`Node ${i}: ${name}=${attr}`);
});
return this;
},
logData() { // Log the data bound to this selection.
console.log(this.data());
return this;
},
logNodeData() { // Log datum per node.
this.each(function(d, i) {
console.log(`Node ${i}: ${d}`);
});
return this;
}
};
Object.assign(d3.selection.prototype, logger);
d3.select("body")
.logMsg("Start")
.append("svg").selectAll(null)
.log(1, {}, "Test")
// .logSel() // this doesn't work well in Stack snippets
.data([1,2])
.enter().append("circle")
.attr("r", "10")
.logAttr("r")
.logData()
.logNodeData()
.logMsg("End");
<script src="https://d3js.org/d3.v5.js"></script>
D3 中是否有允许 "in-line" 日志记录的基础 function/object?
我正在阅读 Scott Murry 的精美 D3 书并想这样做:
d3.select("body").selectAll("div")
.log("body")
.data(dataset)
.log("data")
.enter()
.log("enter")
.append("div")
.log("div")
.attr("class", "bar")
.log("class");
我目前正在做这件可怕的事情:
const log = function (msg, val) {
const data = val ? val : this
const label = msg ? msg : "data:"
console.log(label, data)
return data
}
Object.prototype.log = log
这工作正常,产生了这个可点击的控制台输出:
为了在你的链中记录数据,你可以只使用一个假属性:
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("fake", d=> console.log(d));
对于其他事情,我认为没有 "d3" 允许登录的方式,遗憾的是,我认为您必须以正常方式进行:
console.log(d3.select("body").selectAll("div").data(dataset).enter());
您可以通过修改 d3 选择原型来使用您的解决方案(相对于对象原型,我认为这不能被考虑 "horrible" - 尽管我有点偏向于乱用 d3内部),但我觉得您正在寻找 selection.call()
.
如果您想访问当前选择,但不想中断方法链接,selection.call
可能是您最好的选择:
Invokes the specified function exactly once, passing in this selection along with any optional arguments. Returns this selection. (docs)
被调用函数的第一个参数将是选择,更多的可选参数可以在调用方法本身中传递。一般形式为:
selection.call(func, arg, arg, ...)
function func(selection, arg, arg, ...) {}
使用 selection.call
进行日志记录应该不会太难使用这种方法。这是一个快速模型 (v4/5):
var dataset = d3.range(10);
d3.select("body").selectAll("div")
.call(log,"body")
.data(dataset)
.call(log,"dataset")
.enter()
.call(log,"enter")
.append("div")
.call(log,"div")
.attr("class", "bar")
.call(log,"bar");
function log(sel,msg) {
console.log(msg,sel);
}
结果:
Here's 实际模型。
我首先想到的是 Andrew Reid 在他 selection.call()
. Although that solution is fine, I think it can be improved by directly extending D3's selection. The docs on d3.selection()
中明确提出的方法,即此函数可用于扩展选择原型。
您可以按照以下几行创建自己的记录器:
const logger = {
log() {
console.log(...arguments);
return this;
}
}
这可以很容易地混入d3.selection.prototype
:
Object.assign(d3.selection.prototype, logger);
简单方法 logger.log()
只是记录所有传递给控制台调用的参数,并通过返回 this
来促进方法链接,它指的是选择本身。
当然,可以很容易地想象出许多更有用的日志记录方法,用于打印属性、选择、数据等等。以下演示扩展了基本概念:
const logger = {
log() { // Generic method logging all arguments.
console.log(...arguments);
return this;
},
logMsg(msg) { // Logging just a simple msg.
console.log(msg);
return this;
},
logSel() { // Log the selection.
console.log(this);
return this;
},
logAttr(name) { // Log the attributes with "name" for all selected elements.
this.each(function(d, i) {
let attr = d3.select(this).attr(name);
console.log(`Node ${i}: ${name}=${attr}`);
});
return this;
},
logData() { // Log the data bound to this selection.
console.log(this.data());
return this;
},
logNodeData() { // Log datum per node.
this.each(function(d, i) {
console.log(`Node ${i}: ${d}`);
});
return this;
}
};
Object.assign(d3.selection.prototype, logger);
d3.select("body")
.logMsg("Start")
.append("svg").selectAll(null)
.log(1, {}, "Test")
// .logSel() // this doesn't work well in Stack snippets
.data([1,2])
.enter().append("circle")
.attr("r", "10")
.logAttr("r")
.logData()
.logNodeData()
.logMsg("End");
<script src="https://d3js.org/d3.v5.js"></script>