LoginSignup
7
6

More than 5 years have passed since last update.

Haxeでpushstate対応のRouter作った

Last updated at Posted at 2014-04-27

HaxeでSPAを作ろうと思い立ちました。
Haxeで書くのでjQueryに依存しないルーティングライブラリが欲しかったのですがそういったexternが探しても見つからない。
Kazitori.jsというライブラリはexternもあるし、外部ライブラリにも依存してなくていい感じだったのですが、事後処理を登録出来ないところがネックで利用を断念…
そんな訳で自作してしまった。
(Kazitori.jsを調べた後で書き出したせいか、多くの影響をKazitori.jsから受けております。)

RouterHx

RouterHxはjavascriptまたはhaxe(jsターゲット)で利用出来るpushstate対応のrouterライブラリです。

javascriptの他のライブラリに依存することなく利用することが出来ます。

古いブラウザでは動作しません。
リンクをパーマリンクに変換するような気の利いたことも出来ません。

addEventristener,querySelectorAll,pushState(popState)が使えないブラウザはごめんなさい。

ダウンロード

GitHubで公開してます
git clone https://github.com/k-motoyan/routerhx

Haxeの場合はhaxelibからインストール出来ます
haxelib git routerhx https://github.com/k-motoyan/routerhx

基本的な使い方

Routerクラスをインスタンス化して、addメソッドにURL、処理を持つクラス名、クラスから実行したいメソッド名を指定します。

javascriptの場合

function App() {
  this.index = function() {
    console.log("app index");
  }
  this.greet = function(message) {
    console.log(message);
  }
}

var router = new RouterHx();
router.add("/", "App", "index");
router.add("/greet/<message>", "App", "greet");

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router = new Router();
    router.add("/", "App", "index");
    router.add("/greet/<message>", "App", "greet");
  }

  static function main() {
    new Main();
  }
}

class App {
  public function index() {
    trace("app index");
  }
  public function greet(message) {
    trace(message);
  }
}

pushstateしてみる

RouterHxはルーティングを定義するだけではpushStateどころか登録した処理は実行されません。
raisePushStateメソッドを実行することで、対象のセレクタをpushステート対応のエレメントに変化させます。

aタグをクリックしたらrouterに登録した処理を実行させたいといった場合のサンプルです。

javascriptの場合

var router = new RouterHx();
router.raisePushState("a", "click", "href");

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router = new Router();
    router.raisePushState("a", "click", "href");
  }

  static function main() {
    new Main();
  }
}

raisePushStateメソッドは指定したセレクタをまとめてpushState対応のエレメントに変化させるもので、
個別にrouterに登録したURLを実行した時もあると思います。
そういった場合はrunメソッドを実行することで、routerに登録したURLを実行することが可能です。

javascriptの場合

var App = function() {
  this.index = function() {
    console.log("app index");
  }
}

var router = new RouterHx();
router.add("/", "App", "index");
router.run("/");

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router = new Router();
    router.add("/", "App", "index");
    router.run("/");
  }

  static function main() {
    new Main();
  }
}

class App {
  public function index() {
    trace("app index");
  }
}

マイクロフレームワーク風な書き方

RouterHxはルーティングの設定の方法が2つあります。
一つ目は最初に書いたaddメソッドにインスタンス、インスタンスから実行するメソッドを記述する方法でした。
この方法はアプリケーションの規模が大きくなった場合にコードの構造化をやりやすくします。

規模が小さいアプリケーションの場合は、addCbメソッドに単純にコールバックを登録することでもルーティングを登録することが出来ます。

javascriptの場合

var router = new RouterHx();
router.addCb("/", function() {
  console.log("index");
});
router.addCb("/greet/<message>", function(message) {
  console.log(message);
});

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router = new Router();
    router.addCb("/", function() {
      trace("index");
    });
    router.addCb("/greet/<message>", function(message) {
      trace(message);
    });
  }

  static function main() {
    new Main();
  }
}

RouterHxインスタンス単位での事前処理・事後処理

setBeforesetAfterを利用することで、RouterHxのインスタンス単位に事前処理、事後処理を登録することが可能です。

javascriptの場合

var router1 = new RouterHx();
router1.setBefore(function() {
  console.log("router1 proc start.");
});
router1.setAfter(function() {
  console.log("router1 proc end.");
});

var router2 = new RouterHx();
router2.setBefore(function() {
  console.log("router2 proc start.");
});
router2.setAfter(function() {
  console.log("router2 proc end.");
});

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router1 = new Router(),
        router2 = new Router();

    router1.setBefore(_before1);
    router1.setAfter(_after1);
    router2.setBefore(_before2);
    router2.setAfter(_after2);
  }

  inline function _before1(): Void {
    trace("router1 proc start.");
  }
  inline function _after1(): Void {
    trace("router1 proc end.");
  }
  inline function _before2(): Void {
    trace("router2 proc start.");
  }
  inline function _after2(): Void {
    trace("router2 proc end.");
  }
}

RouterHxに登録したインスタンス単位の事前処理・事後処理

RouterHxに登録したインスタンスにbeforeafterメソッドを登録しておくことでそのインスタンスのメソッド実行前・実行後に行う処理を登録しておくことが可能です。

setBeforesetAfterがRouterHxインスタンスのグローバルな事前処理・事後処理であるのに対して、
この方法はRouterHxに登録したインスタンス単位の事前処理・事後処理を登録することになります。
処理の順番は下記のようになります。

setBeforeで登録した処理
beforeメソッドに記述した処理
③RouteHxのルーティングに登録した処理
afterメソッドに記述した処理
setAfterで登録した処理

javascriptの場合

var App = function() {
  this.before = function() {
    console.log("app before");
  };
  this.index = function() {
    console.log("app index");
  };
  this.after = function() {
    console.log("app after");
  };
}

var router = new RouterHx();
router.add("/", "App", "index");

Haxeの場合

import routerhx.Router;

class Main {
  public function new() {
    var router = new Router();
    router.add("/", "App", "index");
  }

  static function main() {
    new Main();
  }
}

class App {
  public function before() {
    trace("app before");
  }
  public function index() {
    trace("app index");
  }
  public function after() {
    trace("app after");
  }
}

今後の展望

作っていたら中々使い勝手いいんじゃない?と思える出来栄えになったので今後もメンテ続けて行けたらと思う。
取り敢えずは↓の実装を進めていきたいな…

  • raisePushStateって名前がおかしいので直す
  • オプションでURLをhash bangに切り替えられるようにする
7
6
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
6