vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

React.jsに触れてみる1

また唐突な路線変更ですが...。

前回までのサーバーサイド言語のJava置き換えに挑戦しているうちに、「ボタンやタブクリックで変更するHTMLは、わざわざHTMLの形で読み込む必要はないんじゃないか」という考えに至りました。

で、切り替えて表示するHTMLをJavascriptに持たせて、ユーザーの動作に応じてページ内容を更新できる(と思う)React.jsを使ってみるのが良いのでは、と思ったので試してみることに。

今回やること

準備

React.jsのダウンロード

FacebookのGitHubにあるReactのページからStarterKitをダウンロードします。

ダウンロードが完了したらZIPファイルを展開して、今回は「react.min.js」と「JSXTransformer.js」を使用することにします。

React-Toolsのインストール

React.jsを使ったプログラミングには、JSXを使うと便利なのですが、Webページから使用するにはコンパイルしてJavascriptとして読み込めるようにする必要があります (JSXのまま使用しようとすると、Webブラウザで警告が表示されます)。

そこで使用するのがReact-Toolsです。で、これをインストールするためにはnode.js / npmが必要となります。

node.jsのインストール

Xubuntuを使っているので、aptからインストールすることも可能でしょうが、最新バージョンのnode.jsをインストールしたい。

Rubyにおけるrbenvのようなツールはないかな〜、と思ったら流石です。 nodebrewというツールを作成・公開してくれている方がいました。

念の為インストール方法を載せておきます。

  1. ターミナルを使って、任意のディレクトリで「git clone https://github.com/hokaccha/nodebrew.git」を実行
  2. ダウンロードしたnodebrewディレクトリに移動して、「perl nodebrew setup」を実行してインストールする
  3. .bashrcに、「export PATH=$HOME/.nodebrew/current/bin:$PATH」を追加してターミナルを再起動する
  4. 「nodebrew install latest」で最新版をインストール(インストール可能なバージョンを確認したい場合は「nodebrew ls-remote」)
  5. 「nodebrew use v0.12.0」を実行して(v以降はバージョン番号)使用するnode.jsを指定する

React-Toolsのインストール

node.jsのインストールが完了したら、「npm install -g react-tools」を実行すればインストール完了です。

React-Toolsを使ってコンパイルする

JSXでコードを書いたあと「jsx --watch src/ js/」を実行します。

  • 「src/」に変換対象のJSXを置いたパスを指定し、変換後のファイル出力先を「js/」の部分で指定します。
  • HTMLからは変換後のファイルへのパスを指定してJavascriptを読み込みます。
  • コマンドに「--watch」とある通り、上記のコマンドを実行すると、自分でCtrl+Cでストップするまで自動ではストップせず、変換対象のディレクトリにあるファイルが更新されたら自動で変化何を行います。

Reactってみる

まずはページを表示するHTMLです。

rcTabTest.html

< !DOCTYPE html >
< html>
  < head>
    < meta charset='utf-8' >
    < title >rcTabTest< /title >
    < link href='css/stylesheet.css' rel='stylesheet' / >
  < /head >
  < body >
    < main id='main' >
    < /main >
    < script src='js/react.min.js' >< /script >
    < script src='js/JSXTransformer.js' >< /script >
    < script src='js/jquery-2.1.3.min.js' >< /script >
    < script src='js/javascript.js' >< /script >
  < / body >
< / html >
  • 「< div id='tabs' >< /div >」「< main id='main' >< /main>」の部分に、Javascriptからボタン、タブ(ラジオボタンで作成)を追加します。
  • CSSは、これをそのまま使用しています。

さて、肝心のjavascriptです。

javascript.js

(function () {
  var intRightTabNum = 2;
  var ShowTabs = React.createClass({
    getInitialState: function() {
      return {checked: false};
    },
    moveTab: function(event){
      switch (event.target.id){
        case 'arrow_button_left':
            // 一つ左隣のTabを表示.
            intRightTabNum--;
        console.log("left");
            break;
        case 'arrow_button_right':
            // 一つ右隣のTabを表示.
            intRightTabNum++;
        console.log("right");
            break;
        }
    },
    movePage: function (event) {
        var strTargetId = '#' + event.target.id;
        var intNewPageNum = jQuery(strTargetId).data('tabNum');
      console.log("changed" + intNewPageNum);
    },
    render: function() {
      return (
        < section id='tab_frame' >
          < input id='arrow_button_left' class='button_arrow' type='button' onClick={this.moveTab} / >
          < label class='arrow_label' htmlFor='arrow_button_left' ><< /label >
          < input id='tab_0' className='tab_radio' type='radio' name='tabs' data-tab-num='0' onChange={this.movePage} / >
            < label id='tab_label_0' className='tab_label' htmlFor='tab_0' >タブ1< /label >
          < input id='tab_1' className='tab_radio' type='radio' name='tabs' data-tab-num='1' onChange={this.movePage} / >
            < label id='tab_label_1' className='tab_label' htmlFor='tab_1'>タブ2< /label >
          < input id='arrow_button_right' className='button_arrow' type='button' onClick={this.moveTab} / >
          < label id='arrow_label' htmlFor='arrow_button_right' >>< /label >
        < /section >
      );
    }
  });
  React.render( < ShowTabs/ >, document.getElementById('main'));
}).call(this);
  • 「movePage」、「moveTab」というボタンやタブ押下時に呼ばれる関数の中身は(今はログを表示しているだけですが)同じです。

  • 「React.createClass」に、表示するHTMLやイベント処理などを記述します。

  • 作成した「React.createClass」は、「React.render(<変数名/>, HTMLを出力する対象のIDや要素);」から呼び出されます。

    • ※ここで使用する変数名は大文字から始まる必要があり、小文字で「showTabs」のように書いてしまうとスルーされてしまい、実行できませんでした。
  • inputタグで、onChangeを検出するためには状態を監視しておく必要があり、「getInitialState」で初期値の設定を、該当の要素には「checked={this.state.checked}」を持たせる必要があります。

  • Labelタグの「for」は、現在開発版のみでの対応?のようで、代わりに「htmlFor」としてやる必要があります。

その他、複数「React.createClass」を作成できるのか、できる場合はその切り替え方法など、引き続き調べてみたいと思います。

また、今日作成したものはCSSが効いているようですが、CSSJavascriptの中に埋め込んでしまおう、という話もあるようで、こちらも合わせて調べてみたいと思います。

参考

nodebrew

React.js

2015/03/22 訂正

  • rcTabTest.htmlの、JavascriptからHTMLを出力するタグを「< main id='main' >」に変更しました(HTMLの構成を元のページと揃えるため)
  • javascript.jsの「render: function() {〜」のHTMLで、タグに付与した「class」を「className」に変更しました(Labelの「for」と同じく、そのままだとHTMLのclassとして動作しないためです)
  • 「checked={this.state.checked}」を削除しました(このままだとラジオボタンをチェックしても反映されないためです)