読者です 読者をやめる 読者になる 読者になる

albatrosary's blog

Azure と Angular と Wercker CI とか

AngularJS、KnockoutJS、Sencha Ext JSで実装されているデータバインディングの違いをコーディングすることで明らかにする!

AngularJS KnockoutJS Sencha Ext JS

AngularJSを筆頭にKnockoutJSとSencha Ext JSでもデータバインディングが実装されました。この違いを簡単なサンプルを作ることで比較します。JavaScriptフレームワーク選定で個々の特徴を他者から聞き取るだけでなく、実際に同じ機能を様々なフレームワークで実装してみるというのは重要なことと考えます。

 

比較するプログラム

今回作成するプログラムはテキストボックスを二つ配置しテキストボックスに入力された値を足し、合計を表示するというものを作ります。

f:id:albatrosary:20140623133851p:plain

仕様は「テキストボックスに入力された値を即時計算し答えを表示する」ということにします。画面の構成は、ここでの評価は意味のないものですので、こだわりなく作成しました。

AngularJSの場合

AngularJSの場合は、JavaScriptを一行も書かずにその仕様を満たすことができます。index.htmlに次の行を記載しますが、以上で終了です。

<input type="number" ng-model="txt1" ng-init="txt1=0"> +
<input type="number" ng-model="txt2" ng-init="txt2=0"> =
{{txt1 + txt2}}

f:id:albatrosary:20140623185009p:plain

KnockoutJSの場合

KnockoutJSの場合はindex.htmlに下記を記載するのと、それを監視するためのJavaScriptを記載する必要があります。ここで、valueUpdateは、キー入力に対して結果を即時反映するために記載しています。このプロパティが無い場合は、テキストボックスからカーソルを外したときに結果を反省するという動きになります。

<input type="number" data-bind='value:value1, valueUpdate: "afterkeydown"'> +
<input type="number" data-bind='value:value2, valueUpdate: "afterkeydown"'> =
<span data-bind="text:result"></span>

JavaScriptは次の通りです。ごく普通のロジックですが

  • observable
  • computed

の二つでバインディング定義をしています。この二つを記載すればバインディングされるということです。

$(function() {
function ViewModel() {
var _this = this;
_this.value1 = ko.observable(0);
_this.value2 = ko.observable(0);
_this.result = ko.computed(function(){
return parseInt(_this.value1()) + parseInt(_this.value2());
});
};
ko.applyBindings(new ViewModel());
});

マッピングに関するところとバインディングの宣言についてはJavaScriptで記載する必要がありますが、簡単なロジックですし変わったところがありませんのですんなりと組めると思います。

f:id:albatrosary:20140623185132p:plain

Sencha Ext JSの場合

ViewModelの定義は次の通りです。ここでポイントは数値計算にformulasを使用しているところです。これは、値関数呼び出しによって管理されている名前付きの値を定義するオブジェクトということです。他のフレームワークと異なり計算するためには別のオブジェクトを利用するという仕様です。

Ext.define('MyApp.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
data: {
name: 'data binding for Sencha',
txt1: 0,
txt2: 0
},
formulas: {
ans: function (get) {
var fn = get('txt1'), ln = get('txt2');
return fn + ln;
}
}
});

Viewは次のように定義しています。bind: {hoge}と書いてある部分がViewModelと実際にデータバインドする部分になります。Senchaのコードを見慣れていない人は少し難しいかと思いますが、この記述方法はSenchaの特徴でもあります。

Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Container',
xtype: 'app-main',
controller: 'main',
viewModel: {
type: 'main'
},
layout: {
type: 'border'
},
items: [{
xtype: 'panel',
bind: {
title: '{name}'
},
region: 'center',
html: '<ul><li>This area is commonly used for navigation, for example, using a "tree" component.</li></ul>',
width: 250,
split: true,
tbar: [{
xtype: 'numberfield',
bind: '{txt1}'
}, {
xtype: 'numberfield',
emptyText: '0',
bind: '{txt2}'
}, {
xtype: 'label',
bind: '{ans}'
}]
}]
});

Viewに関してはViewModelの結果を純粋に表示することに専念するのが良く、何かしらの処理はViewModelで行う方針が適切だと考えられます。

f:id:albatrosary:20140623185252p:plain

最後に

簡単なサンプルを使ってプログラミングの観点からデータバインディングの構造の違いをAngularJS、KnockoutJS、Sencha Ext JSについて評価してみました。

こうして見るとそれぞれのフレームワークの特徴が見えて来ます。どのフレームワークが最も優れているかという議論はあまり面白くないので行いませんが、フレームワークとしての特徴や仕組み、考え方をしっかりと把握することが出来たと思います。

個々のJavaScriptフレームワークを理解することで、アーキテクチャの理解が深まる一方、このブログがJavaScriptフレームワークの選定の一部になればと思います。それぞれの特徴を見極めて使うのがアプリケーション開発には重要だと考えます。