@tsuchikazuです。半年ほど仕事でAngularと戯れています。
3/21に開催されたng-japanでは、あと1週間後ほどでリリースされるとアナウンスされていたAngular 1.4
あれから10週間ほど経った5/27。ついに、Angular1.4の安定版がリリースされました。
Developer Guide: Migrating from 1.3 to 1.4とCHANGELOGから、Breaking Changeを中心に簡単にまとめましたので、公開します。
概要
Angular1.4では、主にngAnimateの大きなリファクタリングと、ngMessagesの機能改善、$cookiesへの新しいAPIが追加されました。
ngAnimateのリファクタリングは、今まで存在していたissueやバグフィックスと、より便利なアニメーションを提供するための新APIのために行われました。これまでJavascriptとCSSアニメーションは、同時に実行することができていましたが、1.4からはできなくなります。しかし、同じ効果を出すために$animateCssが新しく提供されました。$animateCssを使うことで、JavascriptからCSSアニメーションを扱うことができ、今までより柔軟なアニメーションを提供できます。
ngModule.animation('.slide-animation', ['$animateCss', function($animateCss) {
return {
enter: function(element, doneFn) {
// this will trigger a `.ng-enter` and `.ng-enter-active` CSS animation
var animation = $animateCss(element, {
event: 'enter'
// any other CSS-related properties
// addClass: 'some-class',
// removeClass: 'some-other-class',
// from: {},
// to: {}
});
// make sure to read the ngAnimate docs to understand how this works
animation.start().done(doneFn);
}
}
}]);
ngMessagesは、エラーメッセージを動的に表示するための機能として、エラーメッセージの配列を受け取ることが出来るようになり、ng-repeat
などで自由に表示することができます。ng-message-exp
directiveも新しく提供されました。
<div ng-messages="myForm.myEmail.$error" role="alert">
<div ng-message="required">You did not enter your email address</div>
<div ng-repeat="errorMessage in errorMessages">
<!-- use ng-message-exp for a message whose key is given by an expression -->
<div ng-message-exp="errorMessage.type">{{ errorMessage.text }}</div>
</div>
</div>
$cookies
は、$cookieStore
がdeprecatedになり、$cookies
に統合されました。また、pathやdomainを指定できるようになりました。
var id = $cookies.get('id');
$cookies.put('id', id);
var object = $cookies.getObject('objectKey');
$cookies.putObject(object);
$cookies.put('key','value', {
path : '/',
expires : new Date(2015,7,1)
secure : false,
domain : 'tsuchikazu.net'
});
パフォーマンス面では、digest timeが最大30%、メモリ使用量は2%〜4%改善されています。その他、ngRepeat
、ngOptions
、$http
、filter
などで細かな変更が入っていますが、大きな変更はないため1.3から1.4へは簡単にmigrationできるでしょう。
では、細かいBreaking Changeを紹介します。
Breaking Change
Animation
c8700f0によって、animationに関するcallbackに$animate
を使うようになります。
// < 1.4
element.on('$animate:before', function(e, data) {
if (data.event === 'enter') { ... }
});
element.off('$animate:before', fn);
// 1.4+
$animate.on(element, 'enter', function(data) {
//...
});
$animate.off(element, 'enter', fn);
c8700f0によって、$animate.enabled()
の引数の順番が変わります。
// < 1.4
$animate.enabled(false, element);
// 1.4+
$animate.enabled(element, false);
c8700f0によって、 $animate.enabled(element, false)
した際に子要素のanimationがdisabledになっていましたが、自要素もdisabledになります。
c8700f0によって、animation promiseのthenの中で$scope.apply
や$scope.$digest
をする必要がなくなります。
// < 1.4
$animate.enter(element).then(function() {
$scope.$apply(function() {
$scope.explode = true;
});
});
// 1.4+
$animate.enter(element).then(function() {
$scope.explode = true;
});
Forms(ngMessages, ngOptions)
ngMessages
c9a4421によって、ng-messages-include
の指定場所がng-messages
のattributeからng-messages
の子要素に移動しました。
<!-- AngularJS 1.3.x -->
<div ng-messages="model.$error" ng-messages-include="remote.html">
<div ng-message="required">Your message is required</div>
</div>
<!-- AngularJS 1.4.x -->
<div ng-messages="model.$error">
<div ng-message="required">Your message is required</div>
<div ng-messages-include="remote.html"></div>
</div>
ngOptions
7fda214によって、展開されるのvalueの値が、indexやkeyだったものが、hashKeyが出力されるようになります。
<!-- AngularJS 1.3.x -->
<select ng-model="x" ng-option="i in items">
<option value="1">a</option>
<option value="2">b</option>
<option value="3">c</option>
<option value="4">d</option>
</select>
<!-- AngularJS 1.4.x -->
<select ng-model="x" ng-option="i in items">
<option value="string:a">a</option>
<option value="string:b">b</option>
<option value="string:c">c</option>
<option value="string:d">d</option>
</select>
ngModelへの反映は変わらないため、valueに依存しない限り影響はありません。
valueに依存している場合はtrack by
を使って、回避することができます。
7fda214によって、(key, value) in obj
syntaxを使った場合、keyのアルファベット順にソートされていたものが、Object.keys(obj)
の順番になります
Templating (ngRepeat, $compile)
ngRepeat
c260e73によって、(key, value) in obj"
syntaxを使っている場合、keyのアルファベット順でソートされていたのが、for key in obj
の順番になります
$compile
6a38dbfによって、directiveのscopeに&
で関数を受け取るようにしていて、directive使用時に関数を渡さなかった場合、空の関数がセットされていたが、undefinedがセットされるようになります。
Cookies (ngCookies)
38fbe3eによって、$cookies
のプロパティへのset/get
はできなくなり、get/put
メソッドを呼び出すようになります。
// < 1.4
var id = $cookies.id;
$cookies.id = id;
// 1.4+
var id = $cookies.get('id');
$cookies.put('id', id);
1.3までは、文字列や数値のcookieへの保存/参照は$cookies
、オブジェクトの保存/参照は$cookieStore
というように、分かれていました。1.4からは、$cookies
に以下のメソッドが増え、$cookieStore
はdeprecatedです。
- get
- put
- getObject
- putObject
- getAll
- remove
Server Requests ($http)
5da1256によって、transformRequest
によってheader
などを書き換え可能だったのが、もともと意図した使われ方では無かったため、書き換え不可になります。
// < 1.4
function requestTransform(data, headers) {
headers = angular.extend(headers(), {
'X-MY_HEADER': 'abcd'
});
}
return angular.toJson(data);
}
// 1.4+
$http.get(url, {
headers: {
'X-MY_HEADER': function(config) {
return 'abcd'; //you've got access to a request config object to specify header value dynamically
}
}
})
Filters(filter, limitTo)
filter
filterされる値にarray以外が指定された場合、何も置きなかったのが、エラーになります
limitTo
limitに不正な値が指定された場合、空のobjectやarrayを返していたのが、そのまま返すように変わります。
おわりに
このように、1.4では大きなBreaking Changeがありません。今、仕事で開発しているものは、$cookies
の修正をするだけで、ほぼテストが通りました。
みなさん早速バージョンアップしていきましょう。使用しているAngularモジュールへのプルリクエストも出すチャンスですので、みんなで修正して1.4の世界で生きていきましょう。
間違いなどあったら、ご指摘・編集リクエストお願いします。
そして、次へ待ち構える1.5や、2.0への準備も忘れずに。