12
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

WantedlyAdvent Calendar 2015

Day 10

Durandal.jsに入門したはなし

Last updated at Posted at 2015-12-10

唐突に名前がかっこよさそうなJSフレームワークを触って遊ぶことにしました👏

Durandal.jsとは

durandal.png
そもそもDurandal.jsとはなんなのか。

MVCでもMVPでもMVVMでもなんでもござれみたいな感じで公式には書いてあるがぱっとみではMVVMっぽい(そもそもKnockoutJSがのってるわけだし)

フレームワーク自体の特徴はどんなものなのか、ということでその謳い文句をチラと読んでみるとこんなことが書いてある。

We didn't try to re-invent the wheel. Durandal is built on libs you know and love like jQuery, Knockout and RequireJS. There's little to learn and building apps feels comfortable and familiar. Dive in and enjoy.

どうやらKnockoutJS, jQuery, RequireJSと絡み合ってゴニョゴニョする
フレームワークらしい

調べてもあまり日本語の記事が出てこなかったので、国内ではあんまり有名じゃなかったのかな? と思ったり、Githubの最新コミットが大体一年前でフレームワークの開発自体はもうそんなに活発じゃなかったりで、いろいろ調べているうちに明らかにチョイスが間違えていることに気づき始めたけれど、もう後戻りする時間がないので今回はこの若干出落ち気味のJSフレームワークを紹介します👏

試す

bowerが使えるのでそこからインストールする。

Bash
$ mkdir durandal-example
$ cd durandal-example
$ bower install durandal knockout jquery requirejs --save

jQueryはDurandalの依存関係を無視して最新版をいれないと、バージョンが古いせいで意味の分からないエラーがでるので注意。

インストールが終わったらindex.htmlとエントリポイントになるmain.jsを用意する

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <div id="applicationHost"></div>
    <script src="bower_components/requirejs/require.js" data-main="js/main.js"></script>
  </body>
</html>
main.js
requirejs.config({
  paths: {
    "text": "../bower_components/requirejs-text/text",
    "durandal": "../bower_components/Durandal/js",
    "plugins": "../bower_components/Durandal/js/plugins",
    "knockout": "../bower_components/knockout.js/knockout",
    "jquery": "../bower_components/jquery/dist/jquery"
  }
});

define(function(require) {
  var app = require("durandal/app");

  app.title = "Durandal Example"
  app.configurePlugins({
    router: true,
    dialog: true
  });

  app.start().then(function() {
    app.setRoot('shell');
  });
});

なにかルートになるモジュールを用意する。この場合はshell.jsがそれにあたる。モジュールに対応するビューは同じ名前を持つのでこの場合はshell.htmlになる(後述)

shell.js
define(function(require) {
  var app = require("durandal/app");
  var ko = require("knockout");

  var objects = {
    name: ko.observable(),
    sayHello: function() {
      alert("Hello! " + this.name());
    }
  };

  return objects;
});
shell.html
<div>
  <label>Name</label>
  <input type="text" data-bind="value: name, valueupdate: 'afterkeydown'" />
  <button type="submit" class="btn" data-bind="click: sayHello">Say!</button>
</div>

はい、できましたね。「Say!」と書いてあるボタンを押すとダイアログがでます。

スクリーンショット 2015-12-09 19.47.59.png

スクリーンショット 2015-12-09 19.49.44.png

モジュール

モジュールはRequireJSのdefine関数を使って定義できるもので、上の例ではshell.jsがこれにあたる。基本的にDurandal.jsではこのモジュールの組み合わせでアプリケーションを作っていく。

モジュール
define(function(require) {
  return {
    ...
  };
});

定義されたモジュールのインスタンスは最初にrequireされるタイミングで生成され、常にシングルトンオブジェクトになる。

公式によれば、バックエンドサービスっぽいものを作りたいときはこんな感じでthisに生やしていけばよいとのこと。

backend.js
define(function(require){
  var backend = function(user, data){
    this.user = user;
    this.data = data;
  };
 
  backend.prototype.someRoutine = function(){
    ...
  };
 
  return backend;
});

各モジュールは必ずモジュールIDを持っていて、特にオプションを使わなければmain.jsを起点にした相対パスがモジュールIDになる。durandal/systemモジュールのgetModuleIdという関数を使っても、モジュールのインスタンスからIDを取得できる。

ビュー

  • Durandal.jsでは各モジュールがそれぞれルートになるひとつのビューを持っていて、ビューとモジュールのファイル名は同じになる(A.jsに対応するビューのファイルはA.htmlB.jsのときはB.htmlみたいな感じ)
  • 異なった名前のビューとモジュールを紐付けたい時にはviewLocaterというモジュールを使うらしいのだけれど、色々長くなりそうなので今回はやめておく(リファレンスページ: http://durandaljs.com/documentation/View-Location)
  • このデータバインディングの機構のところでKnockoutJSが使われている

コンポジション

Durandal.jsには、オブジェクトコンポジションビジュアルコンポジションの2つがあり、後者がAngularJSのディレクティブ、Vue.jsのコンポーネントにあたるらしきもので、ビューを部分的に適用できる。

htmlだけをコンポジションとしてバインディングするのは非常にカンタン。

header.html
<div>
  <h1>Header</h1>
</div>
main.html
<div>
  <div data-bind="compose: 'header.html'"></div>
  <div>body</body>
</div>

あるいは、モジュール単位でのバインディングをしたいときには、拡張子を含めずにモジュールIDを渡せば良い。

モジュールID指定
<div>
  <div data-bind="compose: 'header'"></div>
  <div>hoge</body>
</div>

この他にもビューとモジュールをそれぞれ別にひとつのコンポジションとしてバインディングする構文などいろいろあるらしいが、触れると厄介なことになりそうなのでここでは省略する。

Pub&Subモデル

durandal/eventsというモジュールを使うと、イベント通知ができるようになる。特に説明すべきこともない名前通りの機能だが、違いとしてはイベントの送出がひとつの方向にしかないというところか。

イベントの送出
app.trigger('customer:new', newCustomer);
イベントのサブスクライブ
app.on('customer:new').then(function(customer) {
  ...
});

イベントにallを指定するとすべてのイベントをサブスクライブできる

アプリケーションの全イベントをサブスクライブ
app.on('all').then(function(event) {
  ...
});

プラグイン

ルーティングを紹介しようと思ったがいまいち直感的にわからなかったので力尽きた
http://durandaljs.com/documentation/Using-The-Router.html

所感

  • Durandal.jsそんなに悪くなかった
  • KnockoutJSを知ってるともっとよさそう

余談

Stackoverflowで見つけたこのスレッドによると、Durandal.jsの開発者はすでにAngular 2.0のチームに合流しているとのこと。また、Durandalの後継にあたるフレームワークはAureliaらしい。正直こっち触ればよかった。

12
13
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
12
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?