紹介
最近リリースしたAngular2が世を騒いている中、ES6を使ってAngularJS 1を書いてみました。
TraceurとES6は知らない人がいるかもしれないので、念のために簡単に説明すると、ESはEcmaScriptの略で元々はブラウザのscript言語ではありましたが、転々とした歴史で今となって仕様を決める組織になりました。今のブラウザで使われているjavascriptは基本にES5から派生したもので、いわばjavascriptの親でもあります。そして、今回使いたいES6はclassが書けるようになりました。今回の記事はES6を使って、AngularJSはどれだけ綺麗にソースコードを整理できるのかを紹介したいと思います。
最後にTraceurをご紹介します。TraceurはGoogleさんより開発されたES6をES5に変換するコンパイラーです。なぜ変換する必要があるかと言うと、まだES6が搭載されたブラウザが少ないため、実際に本番に落とすには安定なES5に変換しないといけません。
インストール
まずnpmでTraceurをインストール
npm install -g traceur
コーディングしてみましょう
下記の2つのファイルを作成
'use strict';
class My {
constructor($scope) {
this._scope = $scope;
this.hello = "hello hoge";
}
getMessage() {
return "hoge message";
}
}
angular.module("myapp",[])
.controller("myCtrl", [ "$scope" ,My]);
<html ng-app="myapp">
<head>
<title></title>
<script src="http://google.github.io/traceur-compiler/bin/traceur.js"></script>
</head>
<body ng-controller="myCtrl as m">
<div ng-bind="m.getMessage()"></div>
<div ng-bind="m.hello"></div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script type="text/javascript" src="build.js"></script>
</body>
</html>
まず、index.jsをコンパイルし、build.jsとして生成されるように次のコマンドを実行し
traceur index.js --out build.js
そうすると、EC5になったbuild.jsが生成されるので、実際にsafariとchromeで確かめると、hello hogeとhoge messageが見られることがわかります。
複数のjsファイルをコンパイル
大規模な設計を目指しているので、当然ながら複数のjsファイルが存在しているはずです。そのケースを次のようにまとめてみました。
ファイル構造
├ es6
│ ├ index.js
│ ├ apple.js
│ ├ banana.js
│ └ watermelon.js
├ build.js
└ index.html
<html ng-app="myapp">
<head>
<title></title>
<script src="http://google.github.io/traceur-compiler/bin/traceur.js"></script>
</head>
<body>
<ul>
<li><a ui-sref="banana">Banana</a></li>
<li><a ui-sref="apple">Apple</a></li>
<li><a ui-sref="watermelon">Watermelon</a></li>
</ul>
<div ui-view></div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script type="text/javascript" src="dist/angular-ui-router.min.js"></script>
<script type="text/javascript" src="build.js"></script>
</body>
</html>
'use strict';
/*jshint esnext: true */
/*global angular: false */
import Banana from "./banana.js";
import Apple from "./apple.js";
import Watermelon from "./watermelon.js";
angular.module("myapp",["ui.router"])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/banana");
$stateProvider
.state('banana', {
url: "/banana",
controller: Banana,
controllerAs: "vm",
template: "<div ng-bind='vm.hello'></div>",
})
.state('apple', {
url: "/apple",
controller: Apple,
controllerAs: "vm",
template: "<div ng-bind='vm.hello'></div>",
})
.state('watermelon', {
url: "/watermelon",
controller: Watermelon,
controllerAs: "vm",
template: "<div ng-bind='vm.hello'></div>",
});
});
apple.jsと同様にwatermelon.jsとbanana.jsを作成しました。ただし、hello変数の中身だけをAppleからWatermelonなど各フルーツの名前に変えました。
'use strict';
class Apple {
constructor() {
this.hello = "hello this is Apple";
}
}
export default Apple;
最後に、コンパイルします。
traceur es6/* --out build.js
すべてのES6のjsファイルをes6というフォルダに収納しているので、コンパイルするときにes6/*と指定すれば良いです。
scopeは?
index.jsを見ると、scopeが存在しているが使われていません。myCtrl as m
の代わりにscopeを使ってもいいのですが、せっかくclassを使うので、さらにAngular2にはscopeが消されたこともわかったし、scopeを使うことは控えました。
参考サイト
http://victorsavkin.com/post/99998937651/building-angular-apps-using-flux-architecture
http://www.sitepoint.com/writing-angularjs-apps-using-es6/
https://github.com/mvolkmann/todo-es6