HTML上の要素をReact.jsコンポーネントに置き換えるライブラリを作ったから見てくれ

# react-provider
github: _https://github.com/morisuke/react-provider_
npm: _https://www.npmjs.com/package/react-provider_

推奨コンパイル環境: __Browserify + Babelify__
動作環境: __IE8+__

## Q. なにこれ？
__A. HTML要素をReact.jsコンポーネントに置き換えるよ__

```js:app.js
// ES6 Class Component
class Component extends React.Component {
    render() {
        return (
            <div className={this.props.className}>
                {this.props.children}
            </div>
        );
    }
}

// Browserifyで読み込み
var provider = require('react-provider');

// selector: Reactコンポーネント
provider({
  '[data-component=component]': <Component />
});
```

```html:index.html(実行前)
<body>

    <div data-component="component" class="wrapper">
        wrapper-text
        <div data-component="component" class="inner">inner-text</div>
    </div>
  
    <script src="./app.js" type="text/javascript">
</body>
```

```html:index.html(実行後)
<body>
 
    <component>
        <div class="wrapper" data-reactid=".0">
            wrapper-text
            <component>
                <div class="inner" data-reactid=".1">inner-text</div>
            </component>
        </div>
    </component>
 
    <script src="./app.js" type="text/javascript">
</body>
```

## Q. どうしておとなしくVue.jsにしなかったんだ
__A. IE8の闇に呑まれた。__

<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr">「babelでIE8対応かーすごいなーあこがれちゃうなー」と高みの見物してたら自分がやる羽目になって血反吐吐いてる</p>&mdash; morisuke (@morisuke_tec) <a href="https://twitter.com/morisuke_tec/status/594137232115507200">2015, 5月 1</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

## こんな人の役に立つかも
* __Vue.js大好き__なんだけど__IE8__に対応しなければいけなくなった → __なんとなく同じように使えるよ__
* Reactが好きでたまらない他のものは触りたくない、だがしかし作るものはSPAではない → __頭を冷やせ__

## 開発の動機
React.jsは```React.render```を叩くことで画面上にコンポーネントを描画します。
しかしReact自体がSPAを構築する前提で組まれていることもあり、```React.render```の第二引数に指定する描画対象要素は単独のnodeでしか渡せない仕様になっています。（nodeListを渡せない）

しかしPHPのビューテンプレートと併用する場合、どうしても複数のコンポーネントを同時に画面に描画したくなります。（フォームヘルパの機能を拡張したい場合など）
それならnodeListをquerySelectorAllで拾って回しながら描画し続ければ良くない？ という発想から生まれたのがこのライブラリです。

## 実装の方針
やりたいことにほぼ合致しているreact-mountというライブラリがあったのですが、ほぼ正規表現による実装であるため手を加えにくく、またIE10で何故か動かなかったので、自分でイチから実装することにしました。
react-mountはJSXをHTML上に書けるようにしていましたが、こちらはあくまでロジックをReactコンポーネントに隠蔽したい考えであった為、```this.props.children```に子要素をReactElementで渡すのみに留めています。

コンポーネントをネストさせて記述した場合に、refsにツリー構造が格納されるようにしようとも思ったのですが、HTML上の記述とコンポーネントの実装に強い依存関係が生まれるため、途中でやめました。
なのでコンポーネント間の通信にはシングルトン化したEventEmitterなどを利用します。
ここらへんはVue.jsの```$on / $broadcast```のイメージで組んでいくとわかりやすいと思います。

## 無駄に力入れたところ
画面上からpropsに値やReactElementを渡せるようにしました。
__data-props__ もしくは __data-props-html__ 属性を指定した要素の中身をコンポーネントに吸い上げます。

```html:index.html
<body>
 
    <component class="wrapper">
        
        <div data-props="element">
            textnodeです
        </div>
        
        <div data-props-html="element">
            <span class="style">htmlです</span>
        </div>
        
    </component>
  
  <script src="./app.js" type="text/javascript">
</body>
```

こうすると```this.props.element```に、```textnodeです``` が、
```this.props.html.element```に、```<span class="style">htmlです</span>``` が格納されます。

```js:component.js
import React from 'react';
class Component extends React.Component {
  render() {
    return (
        <section>
            {this.props.html.element}
        </section>
        );
  }
}
```

```this.props.html``` に格納されるHTMLはReactElementの配列に変換されているので、renderメソッド内で```{this.props.html.element}```のように展開することができます。
サーバサイドから出力した値やDom構造をpropsに受け止めて使いまわすと色々と楽なので是非活用してみてください。

# 最後に
プルリクやissue、お待ちしております。
土日くらいしか直せないんですけど出来るだけ頑張りますよ。

あと@cognitomさんの「[3分でできるnpmモジュール](http://qiita.com/fnobi/items/f6b1574fb9f4518ed520)」を読んで初めてnpmを自作してみたのですが、とても楽しかったです。
npm installで自分の作ったモジュールが落ちてくる爽快感、たまりませんよ。
皆さんも是非挑戦してみてはいかがでしょうか。