AngularJS

ここらでDirective Scopeの@=&をまとめておきたいと思う

More than 3 years have passed since last update.

@=&でピンと来た方、Directiveを使いこなしていますね!

AngularJSの規模が大きくなると、Viewの再利用性を高めるためDirectiveをたくさん自作することになります。再利用性を高めるということはDirectiveやTemplateの抽象度を高めるということになり、特定の$scopeに依存する書き方は好ましくありません。

そこでDirectiveに独自のScopeを定義します。


Directive Scope

Directiveは初期化時にscopeプロパティを持たせることで、独自のscopeを持たせることができます。

angular.module('myApp')

.directive('dirA', function () {
return {
restrict: 'E',
scope: {arr: '@'} // こんなやつ
};
})

ここには@=&の符号が使用でき、様々なサイトでその意味、利用法が解説されているのですが、いまいち分からない。

ということで、実例を付けてまとめてみました。


plnkr

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sample</title>
</head>
<body ng-app="myApp">
<div ng-controller="SampleCtrlA">
<dir-a my-arr="arr"><span ng-repeat="a in arr">{{a}},</span></dir-a>
</div>
<div ng-controller="SampleCtrlB">
<dir-b my-arr="arr"><span ng-repeat="a in arr">{{a}},</span></dir-b>
</div>
<div ng-controller="SampleCtrlC">
<dir-c my-arr="arr"><span ng-repeat="a in arr">{{a}},</span></dir-c>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.js"></script>
<script>
angular.module('myApp', ['ngRoute']);

var link = function (scope, elem, attr) {
console.log(scope.arr);
scope.arr = [6, 7, 8, 9, 10];
console.log(scope.arr);
console.log(scope);
};

angular.module('myApp')
.directive('dirA', function () {
return {
restrict: 'E',
scope: {arr: '@myArr'},
link: link
};
})
.directive('dirB', function () {
return {
restrict: 'E',
scope: {arr: '=myArr'},
link: link
};
})
.directive('dirC', function () {
return {
restrict: 'E',
scope: {arr: '&myArr'},
link: link
};
});

function Ctrl($scope) {
$scope.arr = [1, 2, 3, 4, 5];
}

angular.module('myApp')
.controller('SampleCtrlA', ['$scope', Ctrl]);

angular.module('myApp')
.controller('SampleCtrlB', ['$scope', Ctrl]);

angular.module('myApp')
.controller('SampleCtrlC', ['$scope', Ctrl]);
</script>
</body>
</html>

console.logに吐いてるので、ログを読めばそのまま動きが分かるはずです。以下の解説はこの動作からみた所感で、公式のリファレンスの引用ではありません。


@


  • ViewのHTML内に書いた文字列がそのまま文字列として渡る。

  • AngularJSの式として評価はされない。

  • 筆者の使い方では、link内の$parse()で扱うために@にすることがある。


=


  • ViewのHTML内に書いた文字列が評価され結果が渡る。

  • 親Scopeとバインドされるので、Directive Scope内の変更で親も変化する。

  • 一番よく使う。


&


  • ViewのHTML内に書いた文字列の評価結果を返すための関数が渡る。

  • 親Scopeとはバインドされない。

  • 多くの解説で「Viewには関数を指定する」と見受けられるが、文字列、数値、配列、関数、なんでもいい。


  • scope.valのように直接参照するとparentGet(scope, locals)という関数が返ってくるだけである。


    • 値はscope.val()として取り出す。

    • これが関数ならscope.val()()として実行する。



  • バインドされず式は評価されるので、用途を理解すると使いやすい。


@=&以降の書き方

よく忘れてエラーになるのが@=&の書き方。

属性名を指定する場合scope: {arr: '=myArr'}というように、キャメルケースで書くことで、HTML中では<directive my-arr="">といったハイフン繋ぎで使えます。

何も書かない場合、そのままScopeのプロパティ名がHTML上での属性名になります。

× {arr: '=my-arr'} <directive my-arr="">

× {arr: '=myArr'} <directive myArr="">
○ {arr: '=myArr'} <directive my-arr="">

× {my-arr: '='} <directive my-arr=""> // そもそも文法として誤り
△ {'my-arr': '='} <directive my-arr=""> // 動くがチェーンできない

○ {myArr: '='} <directive my-arr="">
○ {myArr: '=arr'} <directive arr="">

--

あとは自作Directiveを量産するだけ!