最近(でもないけど)、javascript 界隈の動きに全然ついていけてないので、
今更だけど、ちょっと気になっていたライブラリを触ってみた。
試してみたのは以下の5つのライブラリでのデータバインディング。
今回は、各種 Form 部品への簡単なバインディングのみのサンプルを作りました。
- <input type="text">
- <textarea>
- <input type="password">
- <input type="checkbox">
- <select>
- <select multiple>
- <input type="radio">
Knockout
Microsoft の Steave Sanderson が開発&メンテナンスしているオープンソースプロジェクト。 Microsoft 製品ではないけど、Visual Studio 2012 のプロジェクトテンプレートに組み込まれた。 Intellisense も効くみたい。 http://knockoutjs.com/<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>
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 を作動させるには以下を実行する。
ko.applyBindings(viewModel);
ただ、上記の <input type="text"> ではフォーカスが外れた時にしか値が変更されなかった。
value バインディング に valueUpdate パラメータを付けると change イベントの他に変更を検知するイベントを追加できた。
<input data-bind='value: stringValue, valueUpdate: "afterkeydown"' />
サンプル:https://jsfiddle.net/hira3/bzprrng2/
AngularJS
Googleと個人や企業のコミュニティによって開発されている、完全にJavaScriptで書かれたオープンソースのフロントエンドWebアプリケーションフレームワーク。 https://angularjs.org/<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>
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
インタラクティブな Web インタフェースを構築するためのライブラリ。 本格的はフレームワークではなく、できる限りシンプルな API でリアクティブデータバインディングと構成可能な View コンポーネントを提供することがゴールだと言っている。 LINEのフロントエンドエンジニアのチームがWeb開発において注目・活用している。 http://vuejs.org/guide/ http://jp.vuejs.org/guide/<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>
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 インスタンスを作成することによって自動起動する。
var vm = new Vue({
// オプション
})
サンプル:https://jsfiddle.net/hira3/nwcaad98/
Angular2
Googleが開発をリードするWebアプリ開発フレームワーク。 AngularJSの後継。 Version2からはJSに限定しないフレームワークとなったためAngularという名称になった。 TypeScriptでの開発が推奨されているみたい。 コンポーネント志向? https://angular.io/<myApp></myApp>
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はFacebookが作っているUIを構築するためのライブラリ。 要はMVCフレームワークでいうところのViewの部分をComponentとして作っていくためのライブラリ。 https://facebook.github.io/react/index.html<div id="container"></div>
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 界隈はどんどん新しいものが出てくるね。
ちょっと勉強しないでいると、あっと言う間に付いていけなくなる。
このままだと、何も自分で判断・選択できなくなっちゃう。
もっと勉強しなきゃ!