• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

主干视图和DOM:第2部分(如何使Backbone与d3.js完美配合)

在本文中,我们将探讨如何使 backbone 与 d3.js 完美配合。本文中的概念应该适用于您打算将 Backbone 与大多数其他也操作 dom 的库一起使用的情况。

Backbone + d3.js 在同一个 DOM 上工作

d3.js由 Mike Bostock 编写,是另一个广泛使用的库,它操纵文档对象模型,主要用于可视化数据。事实上,您可以通过数据可视化的方式获得真正的创意

在最低级别,d3.js 与 html 和/或svg元素交互,并通过将数据绑定到文档对象模型来操作它们的属性。

以下是 d3 如何运行的快速示例:

var numericaldata = [1,2,3,4,5,6];
 
d3.select("body").selectAll("p")
    .data(numericalData)
    .enter()
        .append("p")
        .text(function(d) {
            return "I’m number " + d + "!";
        });

上面的代码执行以下操作:

  1. 选择并创建对body元素的引用

  2. 在该选择中,选择p当前在 DOM 中的所有元素

  3. 将每个元素附加numericalData到选定p元素

  4. 对于尚未存在的每个p元素(即其中的一些元素仍需要附加),创建一个元素并将其添加到 DOMnumericalDatap

  5. 将每个新创建的元素中的文本节点设置为包含一些文本(包括 中的相关数字) pnumericalData

第一次尝试让 Backbone 和 d3.js 玩得很好

利用我们在上一篇文章中学到的知识,这里是一个共享 DOM 操作的实现。

var CoolView = Backbone.View.extend({
 
    render: function() {
        var html = "<p>I am not a number!</p>";
        this.$el.html(html);
        return this;
    },
 
    renderVisualization: function(arrayOfData) {
        d3.select("body")
            .selectAll("p")
            .data(arrayOfData)
            .enter()
                .append("p")
                .text(function(d) {
                    return "I’m number " + d + "!";
                });
    }
 
});
 
var coolView = new CoolView();
coolView.render();
 
var myData = [10, 9, 4, 2, 1];
coolView.renderWithD3(myData);

休斯顿,我们有问题!

假设我们的目标是保留现有p元素并将其他p元素附加到 DOM,当我们执行上述代码时,我们很快就会遇到一个重大问题。

将带有文本“我不是数字”的元素.render() 插入到 DOM 中。p但是会.renderVisualization()选择 DOM 中的所有现有p元素并将内容插入到这些元素中。这会覆盖原始元素中的文本,p尽管我们使用.d3.append()

让 d3.js 和 Backbone 完美结合的解决方案

在这个简单的例子中,至少存在两个简单的解决方案。

  1. 使用更具体的css选择器

  2. 完全使用不同的标签

封锁 DOM 的一部分

对于更复杂的示例,我们可能需要替代策略。一种可能的解决方案是封锁将由其中一个库操作的 DOM 的一部分。例如:

var CoolView = Backbone.View.extend({
    ...
    renderVisualization: function(arrayOfData) {
        d3.select("#visualization")
            .selectAll("p")
            .data(arrayOfData)
            .enter()
                .append("p")
                .text(function(d) {
                    return "I’m number " + d + "!";
                });
    }
 
});
 
var coolView = new CoolView();
 
var myData = [10, 9, 4, 2, 1];
coolView.renderVisualization(myData);

在上述情况下,Backbone 继续管理待创建的视图。但是,假设在 DOM 中的某处(由 Backbone 视图管理的DOM 内部或外部)有一个 id 为“可视化”的元素。我们可以通过将所有与d3相关的 DOM 操作范围限定到该元素来了解这一事实。因此,所有 d3 链式方法,包括.selectAll("p")和.append("p"),都在#visualization.

用子视图封装差异化的 DOM 操作

最后,管理第三方视图功能的另一种方法是使用子视图。这是看起来的样子。

var CoolView = Backbone.View.extend({
 
    render: function() {
 
        var subViewA = new SubViewA();
        var subViewB = new SubViewB();
 
        // set the html content for coolview
        this.$el.html(subViewA.render().el);
 
        // append more html content to coolview
        this.$el.append(subViewB.render().el);
        return this;
    }
 
});
 
// Elsewhere, perhaps in your router...
var coolView = new CoolView();
$('.app').html(coolView.render().el);

在这种情况下,subViewA可能包含非可视化内容,也subViewB可能包含可视化内容。

Backbone + d3.js 的另一种 Shared-DOM 操作方法

有时您需要确保您的 d3 DOM 操作发生在与 Backbone 视图本身相同的上下文中。例如,简单地封锁 DOM 的一部分并#visualization不能保证元素存在于由 Backbone 视图表示的 DOM 部分之内或之外。

一种替代方法是确保您的起始 d3 选择引用与 所指向的元素相同的元素this.$el。但是,如果您倾向于不直接设置el或其任何属性,则很难使用 css 充分定位当前视图。

幸运的是,在 d3.js 库中,有一种方法可以直接选择节点。让我给你介绍一下d3.select(node)。根据文档,此方法:

> 选择指定的节点。如果您已经拥有对节点的引用,例如事件***器中的 d3.select(this) 或全局(例如 document.body),这将非常有用。此函数不遍历 DOM。

此方法允许我们编写以下代码并确保 d3 操作发生在 Backbone 视图的上下文中。

var CoolView = Backbone.View.extend({
 
    // note that "el" is not set directly
 
    render: function() {
        var html = "<p>I am not a number!</p>";
        this.$el.html(html);
        return this;
    },
 
    renderVisualization: function(arrayOfData) {
        d3.select(this);    // will not work, "this" refers to a Backbone object
 
        d3.select(this.el)  //pass in a node reference
            .selectAll("p")
            .data(arrayOfData)
            .enter()
                .append("p")
                .text(function(d) {
                    return "I’m number " + d + "!";
                });
    }
});

结论

总之,在使 Backbone 与其他 DOM 操纵器很好地配合时,有许多考虑因素。

  1. 确保选择正确的元素进行操作。使用特定的 CSS 类和 ID 可以让生活更轻松。

  2. 在任何一个库中巧妙地使用各种 DOM 操作方法都可以大有帮助。一定要明确你真正需要的 DOM 操作(追加、前置、插入、删除)。

  3. DOM 中的循环操作可能很棘手。确保正确的元素受到影响。


文章目录
  • Backbone + d3.js 在同一个 DOM 上工作
    • 第一次尝试让 Backbone 和 d3.js 玩得很好
      • 休斯顿,我们有问题!
    • 让 d3.js 和 Backbone 完美结合的解决方案
      • 封锁 DOM 的一部分
      • 用子视图封装差异化的 DOM 操作
    • Backbone + d3.js 的另一种 Shared-DOM 操作方法
  • 结论