可重用的d3.js组件和继承

时间:2014-06-24 09:12:34

标签: javascript d3.js

我正在尝试按照Mike Bostock的Toward Reusable Charts创建一个可重用的d3.js组件库,并且在创建可重用组件时遇到一些困难,这些组件在内部重用代码。< / p>

库及其 i -th组件看起来像这样:

d3.library = {}

d3.library.component_i = function module() {
    var width = 800,
        height = 800;

    function exports(_selection) {
        ...
    }

    exports.width = function(_width) {
        if(!arguments.length) 
            return width;
        width = _width;
        return this;
    }
    exports.height = function(_height) {
        if(!arguments.length) 
            return height;
        height = _height;
        return this;
    }

    ....

    return exports
}

部分代码,例如&#34;成员&#34;和&#34;方法&#34; heightwidth本质上是样板代码,我会为任何组件 i 复制粘贴。我想重新使用代码。

经典&#34;经典&#34; OO语言,例如Python,编写一些_BaseComponent基类并将其子类化是很自然的。该基类将包含公共成员:

class _BaseComponent(object):
   ...  

   @property
   def width(self):
       ...

   @width.setter
   def width(self, width_):
       ...


class ComponentI(_BaseComponent):

    ...

    # width and height inherited

    ...

因为它是一个Javascript库,所以我想保留Javascript和d3.js&#34;感觉&#34;:功能链,select-call范例,等等。我已经在Javascript(例如,Javscript: The Good Parts)中读了一些关于原型继承的内容,但是那里的对象似乎没有按照上面代码的方式定义(即函数)使用局部变量作为&#34;数据成员&#34;用于单个导出函数,以及&#34;方法&#34;用作&#34;数据成员&#34;)的访问者。

我无法弄清楚如何同时创建一个库

  1. 内部有一个可重复使用的层次结构
  2. 与d3.js的其余部分很好地融为一体,尤其是外部
  3. 基本上,related question提出了相同的观点,但请求特定解决方案的帮助。解决上述2点的任何解决方案都可以,即使它涉及更改所有组件。结构体。

2 个答案:

答案 0 :(得分:2)

我最近遇到了完全相同的问题。建立一个图表库,在制作新类型的图表时不想复制粘贴所有常见的exports属性。

以下是我提出的解决方案:

&#13;
&#13;
Chart = function module() {
        // properties
        this._width = 800;
        this._height = 600;
        this._margin = {
            top: 10,
            bottom: 10,
            left: 20,
            right: 5
        };
        this._title = '';
    }

    // doing stuff
    Chart.prototype.plot = function () {
        console.log('The plot function has not been defined.');
    }

    // setting the properties
    Chart.prototype.width = function (_x) {
        if (!arguments.length) return this._width;
        this._width = _x;
        return this;
    }
    Chart.prototype.height = function (_x) {
        if (!arguments.length) return this._height;
        this._height = _x;
        return this;
    }
    Chart.prototype.margin = function (_x) {
        if (!arguments.length) return this._margin;
        this._margin = _x;
        return this;
    }
    Chart.prototype.title = function (_x) {
        if (!arguments.length) return this._title;
        this._title = _x;
        return this;
    }

    // creating a new type of chart, which inherits from Chart.
    BarChart.prototype = new Chart(); // Here's where the inheritance occurs 
    BarChart.prototype.constructor = BarChart;
    BarChart.prototype.parent = Chart.prototype;

    function BarChart() {
    }
    // 'overriding' the .plot function
    BarChart.prototype.plot = function (_selection) {
        var myTitle = this.parent.title.call(this);
        _selection.each(function (_data) {
            console.log('Plotting ' + _data.length + ' bars of data. The chart is called: ' + myTitle);
        });
    }

    
    
    // usage
    var myBarChart1 = new BarChart();
    myBarChart1.width(250)
        .height(200)
        .title('Population Growth');
    myBarChart1.plot(d3.select("#chart").datum([1, 2, 3, 4, 5, 6])); // Plotting 6 bars of data. The chart is called: Population Growth

    var myBarChart2 = new BarChart();
    myBarChart2.width(50)
        .height(500)
        .title('Music Sales');
    myBarChart2.plot(d3.select("#chart").datum([1, 2, 3, 4])); // Plotting 4 bars of data. The chart is called: Music Sales
&#13;
 <script src="http://d3js.org/d3.v3.min.js"></script>
 <div id="chart"></div>
&#13;
&#13;
&#13;

这意味着我只需要创建一次公共属性,例如宽度和高度,而不是我创建的每种类型的图表。生成的对象调用可以链接,如d3.js.唯一与d3.js使用不一致的是你必须调用.plot()函数来实际绘制图表。我一直无法弄清楚如何直接从BarChart函数中调用它(我尝试从BarChart返回一个绘图函数,但这不起作用)。

如果你想阅读这个主题,这里有一篇关于JavaScript继承的非常棒的文章:http://phrogz.net/JS/classes/OOPinJS2.html

答案 1 :(得分:0)

IMO开发可重用组件的理想方法是将它们开发为打包在单个模块中的组件,这些模块相互依赖,生成更高级别的组件。

开发对象层次结构很难管理,也会削弱图书馆的灵活性。

参见: http://www.cloudshapes.co.uk/exp/london-d3-talk/#/9

实际的代码重用不是通过继承属性,而是通过将可视化开发为不同组件的组合。

因此,重用发生在组件级别而不是属性/行为级别。

NVD3是一个遵循这种结构的库。

上面的代码使用闭包而不是依赖原型继承,并且就我所知,不能以你想要的方式扩展。