LoginSignup
2
2

More than 5 years have passed since last update.

KnockoutHxを使って小規模SPA

Posted at

knockoutjsとhaxeを組み合わせて小規模なSPAを作成してみるサンプルです。

knockoutjsをHaxeで利用するためのexternクラス

pushstateに対応したフロントエンドルーティングライブラリ

サンプルコード

タブメニューをクリックするとページコンテンツが切り替わります。

<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
</head>
<body>
  <div class="jumbotron">
    <section id="header">
        <h1>KnockoutHx Sample</h1>
        <p>Knockoutjs + Haxe sample application.</p>
    </section>
  </div>

  <div class="container">
    <div class="row">
      <div class="col-md-12">
        <section id="menu">
          <ul class="nav nav-tabs nav-justified" data-bind="foreach: menus">
            <li role="presentation" data-bind="css: { active: is_active }">
              <a data-bind="text: name, attr: { href: url }, click: movePage">Top</a>
            </li>
          </ul>
        </section>
        <section id="contents">
          <h1 data-bind="text: title"></h1>
          <p data-bind="text: body"></p>
        </section>
      </div>
    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
  <script src="app.js"></script>
</body>
import js.Browser;
import knockout.Knockout;
import knockout.Observable;
import routerhx.Router;

typedef Menu = {
  name: String,
  url: String,
  is_active: Observable<Bool>,
  movePage: Void -> Void
}

typedef Contens = {
  title: Observable<String>,
  body: Observable<String>
}

class Main {
  static var menus: Array<Menu> = [
    { name: "Top", url: "/", is_active: Knockout.observable(true), movePage: topPage },
    { name: "Outline", url: "/outline", is_active: Knockout.observable(false), movePage: outlinePage },
  ];

  static var contents: Contens = {
    title: Knockout.observable(""),
    body: Knockout.observable("")
  }

  static function main() {
    var menu_dom = Browser.document.getElementById("menu");
    var contents_dom = Browser.document.getElementById("contents");

    Knockout.applyBindings({ menus: menus }, menu_dom);
    Knockout.applyBindings(contents, contents_dom);

    var r = new Router();
    for (menu in menus) {
      r.addCb(menu.url, menu.movePage);
    }
    r.raisePushState("a", "click", "href", menu_dom);
    r.run();
  }

  public static function topPage(): Void {
    switchActiveMenu("/");
    contents.title.set("トップページ");
    contents.body.set("トップページっぽいテキスト");
  }

  public static function outlinePage(): Void {
    switchActiveMenu("/outline");
    contents.title.set("概要");
    contents.body.set("概要ページっぽいテキスト");
  }

  static function switchActiveMenu(target_url: String): Void {
    for (menu in menus) {
      if (menu.url == target_url && menu.is_active.get() == false) {
        menu.is_active.set(true);
      } else if (menu.url != target_url && menu.is_active.get() == true) {
        menu.is_active.set(false);
      }
    }
  }
}

Haxeで書く場合のポイント

  • obserbしたプロパティへのアクセスはgetsetのアクセサを通して行う。
  • ViewModelになる部分は予めtypedefで構造を定義しておく(規模が大きいならクラスを定義する)
  • あとはリンクを踏んだ時の処理を好きなように書けばOK

昨日までに間に合いませんでした、スミマセンでした。

2
2
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
2
2