0

我是一个带淘汰赛和 D3(数据驱动文档)的菜鸟,我想做的是创建一个 JS 对象数组,让 D3 显示。现在我只是在 HTML span 标签中显示一些单词。我想要做的是使显示的名称成为一个可观察的 KO,如果我更改更远的行(date[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');
4

1 回答 1

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
}

或创建一个调用它的绑定处理程序:

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(). 这对于普通绑定来说可能是可以的,比如ifwith,尽管你会想要注意它们。它们不适用于foreach绑定 - 如果您在插入数据绑定的 d3 元素后尝试评估 foreach 绑定,则 Knockout 将混合您放置的元素并导致很多问题。最好允许 d3 的本机数据连接行为做淘汰赛foreach通常做的事情。

于 2016-01-16T00:14:34.237 回答