ウェブビューに限らず、今のコーディングスタイルは、自分でゴリゴリ全部作ったりせず、いろいろ便利アイテムがたくさんあるので、そういうのをどんどん使って開発コストを下げるというのが一般的です。ただ、無駄に入れすぎると重くなったり、関数名がバッティングして正常に動かなくなったりするので、必要なものだけに絞った方がいいです。
また、Web開発の最大の課題は、ブラウザによって微妙に動きが違うので、IE、Chrome、Safari、 Fire Fox、Operaなど、すべてのブラウザでテストする必要があるんですが(ウェブビューの場合は、Android 4.0とか5.0とか、iOS7とか8.1とか)、既存のライブラリーは、そういうのもちゃんと動作確認してくれている場合が多いので、品質の向上にもつながります(信用しすぎると痛い目にあいますが)。
無料のもので、すばらしいプラグインやライブラリがたくさんあるので、それで十分事足りますが、気をつけてほしいのは、ダウンロードして個人で使えるのは無料でも、商用利用する時は有料みたいなのがあったり、MITライセンスといった、無料で商用利用もできるが、どっかにライセンスで指定された記述を入れないといけないとかがあるので(ほとんどの場合がなんかある)注意してください。
jQuery
「将来性があると思う言語」ランキングで、ここ数年ずっとjavascript(HTMLの動きを担当する言語)が1位を獲得していますが、その理由はHTML5の登場とあわせて、jQueryの存在が果たした役割が大きいと思います。
jQueryの登場によって、javascriptのDOM操作(HTMLを書き換える操作)が格段に楽になりました。今やjQueryなしではjavascriptは使えないという人が大半を占めるといっても過言ではありません。
昼間は、請負で企業のシステム開発のお手伝いをしていますが、会社のシステムは、枯れた技術(使い古されているが故に安定している)を使っている場合が多いので、逆に「jQueryなしでも組めますか?」とか聞かれたりします。組めますが、じゃまくさいのであんまり組みたくないというのが本音ですが・・・
それぐらい、今やjQueryはWeb系の開発とは、切っても切れない関係になっています。
一時、モバイル端末は処理速度が遅いので、jQueryよりも軽量のzepTo.jsというのが出たりしましたが、今は端末の性能が向上しているので、jQueryでも全く問題がありません。
jQueryは、必ず入れた方がいいと思います。
Angular.js
javascriptでHTMLの内容を変数に落として何かしら処理し、その変数の内容に応じてHTMLを書き換えるというのが、Webページ(ウェブビュー)での処理の基本的な流れです。HTMLとJavascriptは、連動していません。常に、HTMLの内容をjavascriptに反映、もしくはその逆の処理が必要になります。
Angular.jsは、HTMLが変更されたら即座にJavascriptの変数を書き換え、逆に、Javascriptの変数が書き換えられたら即座に画面に反映させてくれます(双方向データバインディング)。Angular.jsを導入する事によって、コード量が激減します。
ただ、DI(依存性注入)という理念の下に(その考え自体はすばらしいのですが)、独特のコード記述が必要になるので、既存のプログラムにAngular.jsを導入したり、その逆をするのはかなり大変です。
また、開発コストは確実に下がりますが、最初は学習コストもそこそこかかると思います。
私も、結構がっつりAngular.jsを使い込んだ時期がありましたが、確かにコード量は減りますが、双方向といいつつも、入力やタッチイベントから呼ばれた処理しか再描画しないので、Ajaxのような非同期処理で処理した場合は、自分で再描画の処理をしないといけなかったり、別のコントロールの処理を呼び出したりするのが面倒で複雑だったり、結構マイナス要素も多かったです。
唯一無二の、Javascript双方向データバインディングライブラリで一世を風靡したAngular.jsですが、「JsView」というjQueryの開発チームが手がけたものも登場し、将来的にはObject.observe()という名でJavascriptに双方向バインディング機能が標準装備されます。さらに、現在Beta版で開発が進められているAngular2では、DIの概念がなくなって全く別物になるという話があり、Angular.jsとの親和性を売りにしていたONSEN UIも、ONSEN UI2からAngular.js連携は廃止する模様です。現状、確実に各方面でAngular離れが進んでいるといえます。
FastClick.js
ウェブビューで、普通にWebページと同じように画面を作ると、ボタンを押した時の反応が恐ろしく遅いのに気づくはずです。これを見て、「やっぱりネイティブじゃないとあかんわ」という人は、ちょっと勉強不足です。
モバイル端末のブラウザは、以下の3段階を経てボタンがクリックされたと判断します。
①ボタンに指がタッチした ②ボタンから指が離れた ③指が離れてから0.3秒経った
なぜ、0.3秒待つかというと、ダブルタップによるズーム機能というモバイル端末特有の機能が存在するからです。
しかし、実際アプリ上でいちいち指が離れてから0.3秒待っていたら、間違いなくユーザーはイライラするでしょう。
そうした場合の対処方として、ボタンにタッチした時点(touchstart)で、ボタンが押されたと判断するといったテクニックがよく使われます。しかし、touchstartでイベントを発火してしまうとtouchmoveイベント(ドラッグやスクロール)を拾わなくなります。なので、ドラッグとかスクロールさせたいところだけ、onclick(上記の3段階のやつ)イベントにしたりして、onclickとtouchstartとを混在させると、前の画面のボタン操作イベントが次の画面で発火してしまったりする事があります。
たとえば、何かポップアップを開く操作があったとして、そのポップアップ画面で一番下までスクロール(touchmove)させた所の「OK」ボタンを押して(onclick)ポップアップを閉じると、たまたまその「OK」ボタンがあった位置に、元の画面の「終了」ボタン(touchstartで発火)があると、「終了」ボタンもおした事になってしまったりします。
このFastClick.jsは、onclickイベントを3段階待たずに瞬時に発火させると同時に、ちゃんとtouchmoveイベントも拾う優れものです。
ちょっと前に、iOSがアップデートされた時に、FastClick.jsが反応しなくなって、全てのアプリを修正した事がありました。プラグインに頼りすぎると、そういう痛い目にあう事もしばしばです。
underscore.js
jQueryがDOM操作に特化したJavascriptライブラリであるのに対して、underscore.jsは、それ以外のデータ処理に特化したJavascriptライブラリです。
配列操作から、HTMLテンプレート、タイマー制御まで、幅広く便利機能が満載です。
ただ、Angular.jsと併用できない(併用するためのプラグインは存在する)ので注意が必要です。また、逆にjQueryと併用する必要があります。
google charts
jSONでデータを送ってやると、SVG形式でデータが帰ってくるので、それをページ内のDIV要素に書き込むだけで、様々な種類のグラフを描画できます。
グラフだけじゃなくて、テーブルにも対応しています。
グラフのポイントをタップすると、値が数値でポップアップ表示されたり、テーブルの場合はソートしてくれたり、かなりの優れものです。
「マニュアルなしで誰でも使える簡単家計簿」や、開発中の「POOL TIGER ver6」に導入しています。
Taffy DB
javascriptのデータベースといえば、sqliteが定番でしたが、W3C(HTMLやJavascriptの将来の方向性を偉いおっちゃんたちが話し合う組織)で将来的にはsqliteは廃止され、indexed DatabaseというNonSQLデータベース一本に統合されるという話が、数年前からずっと言われ続けてますが、モバイルのブラウザでは、まだ当分sqliteが使えそうな雰囲気です。まあ、時間の問題ではありますが。
sqliteもそうなんですが、indexed Databaseもいろいろ設定が面倒で使いづらい。
普段私は、サーバーでは、MySQLを使っているのですが、ローカルではTaffy DBというのを使っています。
nonSQLではありますが、かなり使い勝手が良くて、しかも高速です。jSONをデータベースとして使っているので、いろいろデータの加工もしやすいです。
ただ、非同期ではないので、重い検索とかをすると、javascriptの処理が止まってしまうというのが難点ではありますが。
React.js
今、web・モバイル開発関連で、一番熱いのが、このReact.jsではないでしょうか?
Facebook社製の、いわゆるMVCフレームワークでいうところのViewの部分をComponentとして作っていくためのライブラリです。facebookやinstagramはもちろん、AirBnBやYahoo、Atlassianなど色々なところで使われるようになってきています。
「React.jsとは」などで検索すると、「色々試していくうちにReact.jsは劇的にラクな事に気がつきました。そして既存のJSフレームワークより遙かに分かりやすい。初めてRailsを見たときと同じぐらいの衝撃がありました。」というような手放しの賞賛の文句が目白押しです。
それでは、そのReact.jsがどれだけ素晴らしいか、見ていきましょう。以下、基本形のサンプルです(参照元はどこかわからなくなってしまいました。)。
<!DOCTYPE html>
<html>
<head>
<script src="http://fb.me/react-0.13.3.js"></script>
<script src="http://fb.me/JSXTransformer-0.13.3.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/jsx">
// 親:<Parent />の定義
var Parent = React.createClass({
// State(※状態は親が管理)
// この値はブラウザを閉じたり、リロードするまでは保持される
getInitialState: function () {
return {
textVal: "",
children: []
};
},
// State(textVal)を変更
setStateTextVal: function(textVal) {
this.setState({ textVal: textVal });
},
// State(children)を変更
setStateChildren: function(textVal) {
var textVals = this.state.children.concat(textVal);
this.setState({ children: textVals });
},
// <Parent />の表示
// ここで子となる<ChildInput />と<Child />を記述
render: function() {
return (
<div>
<p>入力してEnterキーを押す</p>
<ChildInput onChange={this.setStateTextVal} onSave={this.setStateChildren} />
<Child textVal={this.state.textVal} children={this.state.children} />
</div>
);
}
});
// 子1:<ChildInput />の定義(※props経由で親を参照できる)
var ChildInput = React.createClass({
_onChange: function (e) {
this.props.onChange(e.target.value);
},
_onKeyDown: function (e) {
if (e.keyCode === 13) { // Enterキー
this.props.onSave(e.target.value);
e.target.value = "";
}
},
// <ChildInput />の表示
render: function() {
return <input type="text" onChange={this._onChange} onKeyDown={this._onKeyDown} />;
}
});
// 子2:<Child />の定義(※props経由で親を参照できる)
var Child = React.createClass({
// <Child />の表示
render: function() {
var key = 0;
var textVals = this.props.children.map(function (textVal) {
// 時間が同じ。つまり、キーが押されるごとに、まとめて再描画されていることに注目
//(サーバーサイドっぽいと言われる所以)
var date = new Date().toString();
return <li key={key++}>{key}.{textVal}({date})</li>;
});
return (
<div>
<p>{this.props.textVal}</p>
<ul>{textVals}</ul>
</div>
);
}
});
// id='app' に <Parent />を表示する(マウント)
var m = React.render(<Parent />, document.getElementById('app'));
</script>
</body>
</html>
このサンプルコードを一目見て、何をしているのか理解できる人がどれだけいるでしょうか?
テキストボックスに文字を入力して、[Enter]を押下する度に、入力値と入力時の現在時刻がリストに追加されていくだけの、ごく単純なプログラムです。
ちなみに同じ事を、私が推奨しているUnderscore.jsのテンプレート機能を使って実装すると以下のコードになります。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo=" crossorigin="anonymous"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
</head>
<body>
<div>
<p>入力してEnterキーを押す</p>
<input id="textVal" type="text" />
<div id="app"></div>
</div>
<script id="tmp_app" type="text/html">
<p><%= data.textVal %> </p>
<ul>
<% for (var i=0; i<data.textVals.length; i++){ %>
<li><%= i+1 %>.<%= data.textVals[i].textVal %>(<%= data.textVals[i].date %>)</li>
<% } %>
</ul>
</script>
<script>
var data = {};
$(function(){
data.textVals = [];
render();
$("#textVal").bind("keydown", onKeyDown);
$("#textVal").bind("keyup", onChange);
});
function render(){
var compiled = _.template($('#tmp_app').html());
$('#app').html(compiled());
}
function onKeyDown(e){
if (e.keyCode === 13) { // Enterキー
var textVal = $('#textVal').val();
data.textVals.push({
textVal: textVal,
date: new Date().toString()
});
$('#textVal').val("");
data.textVal = "";
render();
}
}
function onChange(){
data.textVal = $('#textVal').val();
render();
}
</script>
</body>
</html>
どちらがいいかは、一目瞭然です。
React.jsを賞賛している人たちは、おそらく、データを加工する度に自分でDOMを操作するという事に慣れていない、もしくは、javascriptを使いこなせていない人たちです(サーバーサイド重視型の開発者)。
このReact.jsもそうなんですが(jsx)、やれCoffee Scriptだの、Type Scriptだの、コンパイルがいらないのがスクリプト言語のいいところなのに、わざわざjavascriptにコンパイルが必要なものが流行っていますが、javascriptはそんな面倒な変換を必要とするほどしょぼい言語ではありません。単に、使いこなせていないだけの話です。
また、React.jsの売りの一つに、仮想DOMで差分だけ変更するので、パフォーマンスが良いというのがありますが、そもそもわけのわからないプラグインやフレームワークを入れまくるから重いのであって、普通にシンプルに作れば、ゲームとかじゃない限り、HTMLの表示というのはそんなに重い処理ではありません。
Facebookのように、画像だらけの何百という投稿を表示するというような場合は、さすがに重くなりますが、それでも仮想DOMというのはそんなに難しい技術ではないので、ちょっと工夫すれば自分で実装できます。
逆に、差分を勝手に書き換えるので、マテリアルデザインで見られるようなアニメーションで動きをつけたりできません。明らかに時代に逆行しています。
別にFacebook社に恨みがあるわけではありませんが、あまりにもFacebook社製というだけで、自分でよく吟味することなしに乗っかりまくってる人が多すぎるので、苦言を呈したくなった次第です。もちろん中には、このReact.jsがベストマッチするものもあると思います。
Vue.js
上記のReact.jsのサンプルコードを、さらにVue.jsというこれまた最近はやりのフレームワークでも作ってみました。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.10/vue.js'></script>
</head>
<body>
<div id="app">
<p>入力してEnterキーを押す</p>
<input v-model="textVal" v-on:keyup.enter="add">
<p>{{ textVal }} </p>
<ul>
<li v-for="row in list">
<span>{{ row.textVal }}({{ row.date }})</span>
</li>
</ul>
</div>
<button onclick="test();">test</button>
<script>
window.onload = function() {
new Vue({
el: '#app',
data: {
textVal: '',
list: []
},
methods: {
add: function () {
var text = this.textVal.trim()
if (text) {
this.list.push({ textVal: text, date: new Date().toString() })
this.textVal = ''
}
},
}
})
}
</script>
</body>
</html>
これは、かなり使えそうです。
Angular.jsよりも、学習コストもかからずに処理速度も高速。
React.jsよりも、簡潔なコードで、可読性も高い。
しかも、他のフレームワークとの組み合わせも自由自在といった感じです。
ionicで作ったアプリは、Angular.jsが組み込まれているので処理が重くて、ajax通信が通常よりやや不安定なので、他のフレームワークで作り変えようと思っています。
まず手始めに「マニュアルなしで誰でも使える簡単家計簿」で、このVue.jsを試したいと思います。
Hammer.js
モバイル端末には、スワイプやピンチ、長押しといった特有のタッチイベントが存在します。
「jQuery mobile」や「ionic」では、そういったタッチイベントを処理する機能が標準実装されていますが、そうでない場合は、自分で実装する必要があります(ionicの最新バージョンではタッチイベント対応は外されたみたいですが)。
touchstart, touchend, touchmoveといったイベントを駆使して「何秒経過した」とか「何ポイント動いた」とかの判断するのは結構大変です。
このhammer.jsを導入する事によって、こういったタッチイベントの実装が非常に簡単にできます。
さらに、hammer-time.jsを使うと(90年代に一世を風靡したラップではありません)、例の0.3秒問題も解決してくれます。
