我是一个带淘汰赛和D3(数据驱动文档)的菜鸟,我正在尝试做的是创建一个JS对象数组,让我显示D3。现在我只是在HTML span标签中显示一些单词。我正在尝试做的是使得显示KO的名称可以观察到,如果我更改下行(日期[0] .name行),视图将获得这些更改。出于某种原因,最后一行似乎没有任何影响。我在理论上说,当我生成HTML并且KO不知道如何找到要更改的正确位置时,我遗漏了一些东西。我在d3.select链的末尾添加了一个“attr(x,y)”调用以尝试添加数据绑定属性,但我认为KO要求它们是唯一的(但我不确定)。任何帮助表示赞赏。
var data = [
{ "id": "1", "name": ko.observable("alpha"), ...
{ "id": "2", "name": ko.observable("bravo"), ...
{ "id": "3", "name": ko.observable("delta"), ...
];
ko.applyBindings(data);
d3.select("body").selectAll("span")
.data(data)
.enter()
.append("span")
.text(
function (d) {
return d.name();
}
);
data[0].name('october');
答案 0 :(得分:1)
如果你想让Knockout与d3一起工作,你需要将敲除绑定应用于你创建的每个元素:
var data = [
{ "id": "1", "name": ko.observable("alpha") },
{ "id": "2", "name": ko.observable("bravo") },
{ "id": "3", "name": ko.observable("delta") }
];
d3.select("body").selectAll("span")
.data(data)
.enter()
.append("span")
.attr("data-bind", "text: name") // Applies the data binding attribute
.each(function (d) {
ko.applyBindings(d, this); // Sets up Knockout to work with the node
});
data[0].name('october');
您只需要应用这些绑定一次 - 当您更改节点时,数据绑定仍然适用。实际上,如果要将绑定重新应用于现有节点,则必须先调用ko.cleanNode()
以删除第一个绑定。
如果您希望在任何绑定上下文中从视图模型中获取此数据,请使用ko.dataFor()
之类的内容来获取父元素的绑定:
var data = ko.dataFor(d3.select("#parent-to-attach-to").node());
或明确订阅绑定:
viewModel.observableIWantToTrack.subscribe(function(newValue) {
// your d3 update code here, using newValue
}
或创建一个调用它的binding handler:
ko.bindingHandler.whateverYouWantToCallYourHandler = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// any initialization logic you need
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// where you perform your actual updates
}
}
使用最适合您情况的解决方案。
还有一点需要注意:绑定不会重新评估,这就是你必须调用ko.applyBindings()
的原因。这对于正常绑定可能没问题,例如if
甚至with
,但您需要注意它们。它们不适合foreach
绑定 - 如果在插入数据绑定的d3元素后尝试评估foreach绑定,Knockout将复合您放置的元素并导致很多问题。最好允许d3的本机数据连接行为执行淘汰赛foreach
正常运行。