2

私はRactiveを使い始めており、再利用可能なコンポーネントを作成する方法をよりよく理解したいと思っています。さまざまな状況で使用できる汎用ウィジェットを作成するのは非常に簡単です。私の問題は、多くの場合、アプリケーション内のデータがウィジェットが期待する形にならないことであり、ウィジェットを拡張してアプリケーション固有のものにする方法がわからないことです。

具体的な例として、折れ線グラフをデザインする Ractive コンポーネントを作成しているとします。私はの線に沿って何かをするだろう

var Chart = Ractive.extend({
  template: chart,
  data: {
    points_to_path: function(points) {
      // whatever
    }
  }
});

のようなテンプレートで

<svg>
  {{# points_to_path(points) }}
    <path d="{{ path }}" />
  {{/ end of path }}
</svg>

このコンポーネントは次のように使用できます

var chart = new Chart({
  data: {
    points: [[1, 2], [3, 4], [5, 6]]
  }
});

ここで、実際にそのようなコンポーネントを使用する必要があるとします。おそらく、私のデータは、上記のように 2 要素配列の配列の形にはなりませんpoints。多分私はもっと似たものを持っています

[
  {
    date: 'aug 2011',
    value: 12.51
  },
  {
    date: 'sep 2011',
    value: 12.38
  },
  ...
]

したがって、私がやりたいことはChart、上記の形式でデータを受け入れる、より具体的なアプリケーションを作成することです。変数Chart.extendへの参照は でハードコーディングされているため、 でこれを行う簡単な方法はわかりません。pointschart.html

Backbone のようなフレームワークでは、ビューがネストされているため、内側のウィジェットをより大きなビューにラップし、外側のビューでデータ変換のロジックを定義することができます。ここから Ractive でどのように進めばよいのかよくわかりません。最初から別の方法でウィジェットを設計するべきだったのかもしれません。

より一般的に言えば、私の問題は、Ractive で小さなコンポーネントを作成できることですが、それらをより大きなものに構成する方法がよくわかりません。

Ractive でコンポーネントを特殊化または拡張する慣用的な方法は何ですか? または、多くのコンポーネントを組み合わせてより大きなアプリケーションにしますか?

4

1 に答える 1

6

考えられる解決策がいくつかあります。どれが慣用的なものかはわかりませんが、一般的に、Ractive の哲学は「うまくいけば、それが正しい解決策です!」です。- 私は著者ですが、慣用的なものを時間をかけて決定するのはコミュニティに任せます.

1. 初期化時に関数を渡す

d3 を使用して散布図を作成する場合、通常は次のようにします。

d3.select( 'circle' ).data( points )
     .enter().append( 'circle' )
       .attr( 'cx', function ( d ) { return d.x; })
       .attr( 'cy', function ( d ) { return d.y; })
       .attr( 'r', 5 );

つまり、それぞれについてデータムx と y の位置をプロットするために必要な値を抽出する関数を提供しました。

Ractive に相当するのは、コンポーネントを初期化するときに関数を指定することです。

<!-- the template -->
<svg>
  <path d='{{ points_to_path(points) }}'/>
</svg>
// let's create a chart component that assumes we get an array
// of points with an `x` and a `y` property
var Chart = Ractive.extend({
  template: chart,
  data: {
    points_to_path: function(points) {
      // is there a 'normalise' function? If so, normalise
      // the data we've been given
      if ( var normalise = this.get( 'normalise' ) ) {
        points = points.map( normalise );
      }

      // turn a normalised `{x: x, y: y}` point into 'x,y'
      var pointToString = function ( point ) {
        return point.x + ',' + point.y;
      };

      // create the SVG path
      return 'M' + points.map( pointToString ).join( ' ' );
    }
  }
});

// now, we need to create a function that tells the Chart
// component how to deal with the data we're about to give it
var chart = new Chart({
  data: {
    points: [[1, 2], [3, 4], [5, 6]],
    normalise: function ( point ) {
      return { x: point[0], y: point[1] };
    }
  }
});

したがって、dateおよびプロパティを持つポイントの配列がある場合は、返される関数 (またはアメリカのスペルを好む場合は...) をvalue渡すだけです。normalisenormalize{x: point.date, y: point.value}

(もちろん、points_to_pathそれがより簡単であれば、代わりに関数全体を上書きすることもできます。)

2.パーシャルの使用

別の方法は、さまざまな状況でさまざまなパーシャルを使用することです。

<!-- widget template -->
<h2>This is a widget</h2>
<div class='contains-dynamic-contents'>
  {{>inner}}
</div>
var widget = new Widget({
  el: 'widgetContainer',
  partials: {
    inner: '<p>This paragraph will appear inside the div</p>'
  }
});

これにより多くの自由が得られますが、折れ線グラフの例は適応するのがおそらくより面倒です。

インライン コンポーネント

最初の方法は、インライン コンポーネントでも機能します。この例では、まもなくリリースされる開発 ( 0.3.8-pre ) バージョンを使用していることを前提としています。

Ractive.components.linechart = Chart;
<div class='application'>
  <h1>This is a chart</h1>
  <linechart points='{{someData}}' normalise='{{someNormaliseFunction}}'/>
</div>

normalise(ヒント: でデフォルトの関数を指定できますChart.data.normalise = someFunction。)

2 番目の方法は少しトリッキーです。初期化時にパーシャルを動的に切り替える必要があります。

Chart = Ractive.extend({
  beforeInit: function () {
    this.partials.inner = ( someCondition ? thisPartial : thatPartial );
  },
  // ...
});

この応答の壮大な長さで申し訳ありません。あなたが望んでいた答えがここのどこかにあることを願っています!

于 2013-12-10T23:20:09.977 に答える