今回は、
前回ではまだ使っていなかった、
m.request
やm.route
などのAPIを使って
ちょっとしたアプリを作ってみました。
APIについては個人的に注意すべき点などを感じたので、
それについて書いてみたいと思います。
m.request
を使うと非同期処理を簡便に書くことができます。
こちらにあるように、
完了時コールバックをPromise風に記述することになるので、
処理の流れも分かりやすくなります。
ただ、m.request(param)
では
JSONやJSONPでの通信を前提としているような所があるので、
生のデータとして受け取るには以下のように
param.deserialize
を設定する必要があります。
param.deserialize = function(value) {return value;};
Mithril.jsの内部的には
XMLHttpRequest
(xhr) のresponseText
を返しているようなので、
基本的にはバイナリとか扱えない感じ。
param.config = function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
};
とかやれば、バイナリ文字列という形で受け取れるが
少々トリッキーだし余計な処理も必要となる。
ということで、バイナリ(arraybuffer)とかで受け取る場合は、
直接、XMLHttpRequest
を使って自前で書いた方が早いかも。
responseType
を指定してresponse
で受けとる方が、
個人的には直感的で分かりやすい気がする。
というか、m.request
のパラメータで
responseType
を指定できるようにすれば良いのに、と思う。
(古いブラウザへの配慮なのかもしれないけど・・・)
param.config
を使うと、以下のように
xhrを置き換えて好きなようにやれるようなのですが、
なんだかなぁ~、という感じになります(^_^;)
param.config = function(xhr,options) {
xhr = new XMLHttpRequest();
.
.
return xhr; // replace
};
また、m.request
のパラメータは色々あって、
使い所がよく分からなかったりするので、
m.request
を使わずにxhrでやった方が分かりやすいこともあるかもしれない。
Mithril.jsの流儀に従うには(というか描画を遅延させるには)、
m.startComputation()
とm.endComputation()
を噛ますだけで済むので、
大して手間も掛からなさそうだし。
例えば以下の様な感じかな。
function request(url,type,onload,onerror) {
var xhr;
m.startComputation()
xhr = new XMLHttpRequest();
xhr.onloadend = function() {
if (this.status === 200) {
onload(this);
} else {
onerror(this);
}
m.endComputation();
};
xhr.open('GET',url,true);
xhr.responseType = type;
xhr.send();
}
次に、
m.route
はこんな感じのAPIです。
複数のComponentを一意にm.mount
できるAPIといった所でしょうか。
いわゆるSPA(Single Page Application)を作るための仕組みだそうです。
SPAというのは、
URLは同じだけど(クエリとかハッシュとかつく場合あり)、
複数のページから成っているかのように振る舞うアプリといった感じかな。
注意点としてはm.route
によってページが切り替わるたびに、
Controllerのコンストラクタがnewされるようなので、
切り替わっても初期化されないようにするためには、
ちょっと工夫が必要です。
以下のように書くと切り替え毎にpropが初期化されてしまうので、
function controller() {
this.prop = 'something';
}
以下のように書く必要があります。
var obj = {
prop: 'something'
};
function controller() {
return obj;
}
newの戻り値はインスタンスとして扱われるので、
上のように書いても問題無いです。
なお、m.route
を使うと
デフォルトではURLにクエリ文字列が付きます。
例えば http://foo/bar/index.html?page1 とか。
m.route.mode
を設定するとハッシュとかに変更できます。
例えば http://foo/bar/index.html#page1 とかになります。
ハッシュにすると名前付きアンカーが使えなくなりますが、
どのブラウザでもページリフレッシュが発生しないようにできるとのことです。
今回作ったアプリでは、
<input type="text">
な入力があります。
入力値を制限するために、
oninput
なイベントを設定しているのですが、
Mithtil.jsでは入力する毎に、
インタラクティブに描画を更新できるようにできます。
これはこれで便利なわけですが、
入力後のOKボタンで確定させるような作りの場合は、
入力毎に再描画が発生するのはムダになります。
m.redraw.strategy('none')
とやれば
次回の再描画をキャンセルすることができます。
ただし効果は1フレームだけなので注意が必要です。
その後にm.redraw.strategy('diff')
に自動で再設定されます。
それから、
Mithril.jsではインジェクションな攻撃とかを防ぐために、
テキストはdocument.createTextNode()
によってエスケープされます。
そのため例えば ' '
と書いても、
「改行しない空白」には成らずに、「 」と単なる文字と成ります。
そのため期待した通りにするには、
m.trust(' ')
と書く必要があります。
んで、作ったアプリというのは
国コードから割り当て済みIPv4を抽出、あるいはその逆を行うというもの。
データはこちらを参照させていただいております。
1日に1回程度更新されているそうなので、
1日分はキャッシュするようにしました。
毎回アクセスするのはサーバーに負荷を掛けることになると思うので。
それにしても、ここを見ると
人口の割にアメリカは確保しすぎだろ!
って、ツッコミたくなりますね(^_^;)
ということで長々と書いてしましましたが、
アプリを試すにはこちらからどうぞ。
IPアドレスから国コードを抽出した際の表示を変更してみました。
国コードはドロップダウンなリストでも選べるようにしてみました。
また、割り当て済みの個数とかの表示を追加してみました。