LoginSignup
7
11

More than 5 years have passed since last update.

今更だけど、いろんな Javascript library で data-binding してみた

Last updated at Posted at 2016-10-23

最近(でもないけど)、javascript 界隈の動きに全然ついていけてないので、
今更だけど、ちょっと気になっていたライブラリを触ってみた。

試してみたのは以下の5つのライブラリでのデータバインディング。

今回は、各種 Form 部品への簡単なバインディングのみのサンプルを作りました。

  • <input type="text">
  • <textarea>
  • <input type="password">
  • <input type="checkbox">
  • <select>
  • <select multiple>
  • <input type="radio">

sample_form.png

Knockout

Vue.js
Microsoft の Steave Sanderson が開発&メンテナンスしているオープンソースプロジェクト。
Microsoft 製品ではないけど、Visual Studio 2012 のプロジェクトテンプレートに組み込まれた。
Intellisense も効くみたい。
http://knockoutjs.com/

HTML
<input type="text" data-bind="value: stringValue" />
<textarea data-bind="value: stringValue"></textarea>
<input type="password" data-bind="value: passwordValue" />
<input type="checkbox" data-bind="checked: booleanValue" />
<select data-bind="options: optionValues, value: selectedOptionValue"></select>
<select multiple="multiple" data-bind="options: optionValues, selectedOptions: multipleSelectedOptionValues"></select>
<label><input type="radio" value="Alpha" data-bind="checked: radioSelectedOptionValue" />Alpha</label>
Javascript
var viewModel = {
    stringValue : ko.observable("こんにちわ"),
    passwordValue : ko.observable("hogehoge"),
    booleanValue : ko.observable(true),
    optionValues : ["Alpha", "Beta", "Gamma"],
    selectedOptionValue : ko.observable("Gamma"),
    multipleSelectedOptionValues : ko.observable(["Alpha", "Gamma"]),
    radioSelectedOptionValue : ko.observable("Beta")
};
ko.applyBindings(viewModel);

HTMLでは data-bind 属性 を使用してバインディングする。
<select> では options バインディング で <option> も生成してくれる。
ViewModel では、ちょっと面倒だけど ko.observable オブジェクトを使う。
こうすることで、値の変化を検知して View が自動的に変更されるようになる。

knockout を作動させるには以下を実行する。

Javascript
ko.applyBindings(viewModel);

ただ、上記の <input type="text"> ではフォーカスが外れた時にしか値が変更されなかった。
value バインディングvalueUpdate パラメータを付けると change イベントの他に変更を検知するイベントを追加できた。

HTML
<input data-bind='value: stringValue, valueUpdate: "afterkeydown"' />

サンプル:https://jsfiddle.net/hira3/bzprrng2/

AngularJS

AngularJS
Googleと個人や企業のコミュニティによって開発されている、完全にJavaScriptで書かれたオープンソースのフロントエンドWebアプリケーションフレームワーク。
https://angularjs.org/

HTML
<input ng-model="formCtrl.stringValue" />
<textarea ng-model="formCtrl.stringValue"></textarea>
<input type="password" ng-model="formCtrl.passwordValue" />
<input type="checkbox" ng-model="formCtrl.booleanValue" />
<select ng-model="formCtrl.selectedOptionValue" ng-options="option for option in formCtrl.optionValues"></select>
<select multiple="multiple" ng-model="formCtrl.multipleSelectedOptionValues" ng-options="option for option in formCtrl.optionValues"></select>
<label><input type="radio" value="Alpha" ng-model="formCtrl.radioSelectedOptionValue" />Alpha</label>
Javascript
angular.module('myApp', [])
  .controller('FormComtroller', function () {
    this.stringValue = 'こんにちわ';
    this.passwordValue = "hogehoge";
    this.booleanValue = true;
    this.optionValues = ["Alpha", "Beta", "Gamma"];
    this.selectedOptionValue = "Gamma";
    this.multipleSelectedOptionValues = ["Alpha", "Gamma"];
    this.radioSelectedOptionValue = "Beta";
});

HTMLでは ng-model 属性 を使用してバインディングする。
<select> では ng-options 属性 で <option> も生成してくれる。
基本的に、AngularJS は ng-app 属性 をトリガーに自動で起動する。

サンプル:https://jsfiddle.net/hira3/f55dp8r5/

Vue.js

Vue.js
インタラクティブな Web インタフェースを構築するためのライブラリ。
本格的はフレームワークではなく、できる限りシンプルな API でリアクティブデータバインディングと構成可能な View コンポーネントを提供することがゴールだと言っている。
LINEのフロントエンドエンジニアのチームがWeb開発において注目・活用している。
http://vuejs.org/guide/
http://jp.vuejs.org/guide/

HTML
<input v-model="stringValue" />
<textarea v-model="stringValue"></textarea>
<input type="password" v-model="passwordValue" />
<input type="checkbox" v-model="booleanValue" />
<select v-model="selectedOptionValue">
    <option v-for="option in optionValues">{{ option }}</option>
</select>
<select multiple="multiple" v-model="multipleSelectedOptionValues">
    <option v-for="option in optionValues">{{ option }}</option>
</select>
<label><input type="radio" value="Alpha" v-model="radioSelectedOptionValue" />Alpha</label>
Javascript
var demo = new Vue({
    el: '#inputForm',
    data: {
        stringValue: 'こんにちわ',
        passwordValue: 'hogehoge',
        booleanValue : true,
          optionValues : ["Alpha", "Beta", "Gamma"],
        selectedOptionValue : "Gamma",
        multipleSelectedOptionValues : ["Alpha", "Gamma"],
        radioSelectedOptionValue : "Beta"
    },
});

HTMLでは v-model 属性 を使用してバインディングする。
<option> は v-for 属性で繰り返し生成する。
Vue インスタンスを作成することによって自動起動する。

javascript
var vm = new Vue({
  // オプション
})

サンプル:https://jsfiddle.net/hira3/nwcaad98/

Angular2

Angular2
Googleが開発をリードするWebアプリ開発フレームワーク。
AngularJSの後継。
Version2からはJSに限定しないフレームワークとなったためAngularという名称になった。
TypeScriptでの開発が推奨されているみたい。
コンポーネント志向?
https://angular.io/

HTML
<myApp></myApp>
Javascript
var MyApp = ng
.Component({
    selector: 'myApp',
    directives: [ng.CORE_DIRECTIVES, ng.FORM_DIRECTIVES],
    template: [
        `<table>
            <tr>
                <td class="label">テキスト値 (タイプ時に更新):</td>
                <td><input [(ng-model)]="stringValue" /></td>
            </tr>
            <tr>
                <td class="label">テキスト値 (複数行):</td>
                <td><textarea [(ng-model)]="stringValue"> </textarea></td>
            </tr>
            <tr>
                <td class="label">パスワード:</td>
                <td><input type="password" [(ng-model)]="passwordValue" /></td>
            </tr>
            <tr>
                <td class="label">チェックボックス:</td>
                <td><input type="checkbox" [(ng-model)]="booleanValue" /></td>
            </tr>
            <tr>
                <td class="label">ドロップダウンリスト:</td>
                <td>
                    <select [(ng-model)]="selectedOptionValue">
                        <option *ng-for="#option of optionValues">{{option}}</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td class="label">複数選択リスト:</td>
                <td>
                    <select multiple="multiple"
                          (change)="onSelectChange($event.target.selectedOptions)">
                        <option *ng-for="#option of optionValues" [selected]="isSelected(option)">{{option}}</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td class="label">ラジオボタン:</td>
                <td>
                    <label><input type="radio" name="radio" value="Alpha"
                        [checked]="radioSelectedOptionValue=='Alpha'" (change)="radioSelectedOptionValue=$event.target.value" />Alpha</label>
                    <label><input type="radio" name="radio" value="Beta"
                        [checked]="radioSelectedOptionValue=='Beta'" (change)="radioSelectedOptionValue=$event.target.value" />Beta</label>
                    <label><input type="radio" name="radio" value="Gamma"
                        [checked]="radioSelectedOptionValue=='Gamma'" (change)="radioSelectedOptionValue=$event.target.value" />Gamma</label>
                </td>
            </tr>
        </table>`
    ]
})
.Class({
    constructor: function () {
        this.stringValue = 'こんにちわ';
        this.passwordValue  = 'hogehoge';
        this.booleanValue = true;
        this.optionValues = ['Alpha', 'Beta', 'Gamma'];
        this.selectedOptionValue = 'Gamma';
        this.multipleSelectedOptionValues = ['Alpha', 'Gamma'];
        this.radioSelectedOptionValue = 'Beta';
    },
    onSelectChange: function (options) {
        var selectedValue = [].slice.call(options).map(o => {return o.text;});
      this.multipleSelectedOptionValues = selectedValue;
    },
    isSelected(value) {
      return this.multipleSelectedOptionValues.indexOf(value) >= 0 || null;
    }
});

document.addEventListener('DOMContentLoaded', function () {
    ng.bootstrap(MyApp);
});

あれ? AngularJS とは別物か?
考え方が全然違うのかな???
まだ全然理解できてないけど、無理やり動くものを作ってみた。
勉強しないとマズイ!!

サンプル:https://jsfiddle.net/hira3/jm4yc7pr/

React

React
ReactはFacebookが作っているUIを構築するためのライブラリ。
要はMVCフレームワークでいうところのViewの部分をComponentとして作っていくためのライブラリ。
https://facebook.github.io/react/index.html

HTML
<div id="container"></div>
Javascript
var InputText = React.createClass({
  handleValueChange: function(e) {
    this.props.onChange(e.target.value);
  },
  render: function() {
    return (
          <tr>
            <td className="label">テキスト値 (タイプ時に更新):</td>
            <td>
                <input value={this.props.value}
                      onChange={this.handleValueChange} />
            </td>
          </tr>
    );
  }
});

var InputTextArea = React.createClass({
  handleValueChange: function(e) {
    this.props.onChange(e.target.value);
  },
  render: function() {
    return (
          <tr>
            <td className="label">テキスト値 (複数行):</td>
            <td>
                <textarea value={this.props.value}
                      onChange={this.handleValueChange}></textarea>
            </td>
          </tr>
    );
  }
});

var InputPassword = React.createClass({
  handleValueChange: function(e) {
    this.props.onChange(e.target.value);
  },
  render: function() {
    return (
          <tr>
            <td className="label">パスワード:</td>
            <td>
                <input type="password" value={this.props.value}
                      onChange={this.handleValueChange} />
            </td>
          </tr>
    );
  }
});

var Checkbox = React.createClass({
  handleChange: function(e) {
    this.props.onChange();
  },
  render: function() {
    return (
          <tr>
            <td className="label">チェックボックス:</td>
            <td>
                <input type="checkbox" checked={this.props.value}
                      onChange={this.handleChange} />
            </td>
          </tr>
    );
  }
});

var Dropdown = React.createClass({
  handleValueChange: function(e) {
    this.props.onChange(e.target.value);
  },
  render: function() {
    return (
          <tr>
            <td className="label">ドロップダウンリスト:</td>
            <td>
              <select value={this.props.value}
                    onChange={this.handleValueChange}>
              {
                this.props.options.map(function (item) {
                  return <option>{item.text}</option>;
                })
              }
              </select>
            </td>
          </tr>
    );
  }
});

var ListBox = React.createClass({
  handleValueChange: function(e) {
    var selectedValue = [].slice.call(e.target.selectedOptions).map(o => {return o.text;});
    this.props.onChange(selectedValue);
  },
  render: function() {
    return (
          <tr>
            <td className="label">複数選択リスト:</td>
            <td>
              <select multiple={true} value={this.props.value}
                    onChange={this.handleValueChange}>
              {
                this.props.options.map(function (item) {
                  return <option>{item.text}</option>;
                })
              }
              </select>
            </td>
          </tr>
    );
  }
});

var RadioButton = React.createClass({
  handleChange: function(e) {
    this.props.onChange(e.target.value);
  },
  render: function() {
    return (
          <tr>
            <td className="label">ラジオボタン:</td>
            <td>
                <label><input type="radio" value="Alpha"
                    checked={this.props.value === "Alpha"}
                  onChange={this.handleChange} />Alpha</label>
                <label><input type="radio" value="Beta"
                    checked={this.props.value === "Beta"}
                  onChange={this.handleChange} />Beta</label>
                <label><input type="radio" value="Gamma"
                    checked={this.props.value === "Gamma"}
                  onChange={this.handleChange} />Gamma</label>
            </td>
          </tr>
    );
  }
});

var MyApp = React.createClass({
  getInitialState: function(){
      return {
          stringValue: 'こんにちわ',
          passwordValue: 'hogehoge',
          booleanValue : true,
          optionValues : [{text:"Alpha"}, {text:"Beta"}, {text:"Gamma"}],
          selectedOptionValue : "Gamma",
          multipleSelectedOptionValues : ["Alpha", "Gamma"],
          radioSelectedOptionValue : "Beta"
      }
  },
  handleInputTextChange: function(text) {
    this.setState({stringValue: text});
  },
  handleInputPasswordChange: function(text) {
    this.setState({passwordValue: text});
  },
  handleCheckboxChange: function() {
    this.setState({booleanValue: !this.state.booleanValue});
  },
  handleDropdownChange: function(value) {
    this.setState({selectedOptionValue: value});
  },
  handleListBoxChange: function(values) {
    this.setState({multipleSelectedOptionValues: values});
  },
  handleRadioButtonChange: function(value) {
    this.setState({radioSelectedOptionValue: value});
  },
  render: function() {
    return (
      <div>
        <h3>Form 部品</h3>
        <table>
            <InputText value={this.state.stringValue}
                        onChange={this.handleInputTextChange}/>
            <InputTextArea value={this.state.stringValue}
                        onChange={this.handleInputTextChange}/>
            <InputPassword value={this.state.passwordValue}
                        onChange={this.handleInputPasswordChange}/>
            <Checkbox value={this.state.booleanValue}
                        onChange={this.handleCheckboxChange}/>
            <Dropdown value={this.state.selectedOptionValue}
                        options={this.state.optionValues}
                        onChange={this.handleDropdownChange}/>
            <ListBox value={this.state.multipleSelectedOptionValues}
                        options={this.state.optionValues}
                        onChange={this.handleListBoxChange}/>
            <RadioButton value={this.state.radioSelectedOptionValue}
                        onChange={this.handleRadioButtonChange}/>
        </table>
      </div>
    );
  }
});

ReactDOM.render(
  <MyApp />,
  document.getElementById('container')
);

React も流行っているみたいだからやってみたけど、全然わからない。orz.
とりあえず、こっちも無理やり動くものを作ってみた。
もっと勉強しないとマズイ!!!!

サンプル:https://jsfiddle.net/hira3/6qnazs9n/

これって何が良いのか全然わからなかった。
以下を見てみたら少しわかった気がする (^^;
Reactがなぜ素晴らしいのか by Yuichiro MASUI
ReactとFluxのこと by geta6

まとめ

Javascript 界隈はどんどん新しいものが出てくるね。
ちょっと勉強しないでいると、あっと言う間に付いていけなくなる。
このままだと、何も自分で判断・選択できなくなっちゃう。
もっと勉強しなきゃ!

7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11