将Knockout与D3混合 - 更新视图

时间:2013-10-30 20:15:17

标签: data-binding knockout.js d3.js

我是一个带淘汰赛和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');

1 个答案:

答案 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正常运行。