AngularJs开发——指令与控制器间的通信

指令与控制器之间通信

  1. 通过指令自身参数
  2. 基于event传播的方式
  3. service的方式

方式一:指令参数共享对象/方法

首先我们必须得清楚,每一个 $scope 都是scope的一个事例,而通过绑定将数据绑定在 $scope 就能实现双向绑定。scope的层次结构跟controller相关,继承关系跟又遵循了原型继承的规则,而子controller所初始化的scope是创建一个新的变量,而不是去修改父controller中的值。所以就不难使用为什么不使用基本类型变量而是使用引用类型变量去实现控制器间的通信。

指令中怎么创建 scope:

  • scope默认值是false,表示scope跟父controller的scope相同
  • scope:true,表示创建一个继承自父scope的新scope,这样就可以让同一个父控制下的指令都可以使用这个scope进行通信。
  • 创建完全独立的属于指令自己的scope,这样可以防止读取和修改父级scope的数据。

创建完全独立的scope的API:

  • =:提供一个与父scope的双向绑定的属性。
  • &:能够在指令内访问定义在父scope注册的函数。
  • @:提供一个 父scope-》子指令的单向绑定的属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var app = angular.module('app', []);
angular.element(document).ready(function readyHandler() {
angular.bootstrap(document, ['app']);
});
app.controller('demo', function($scope){
$scope.num = 0;
$scope.add = function(){
$scope.num++;
};
});
app.directive('addNum', function() {
return {
restrict: 'EA',
replace: true,
scope : {
num: '=num',
add: '&'
},
template: '<p><button ng-click="add()">点我</button>{{num}}</p></div>',
link: function($scope){
}
};
});

view JSbin

方式二:通过服务

通过 services 实现控制器与指令双向通信,也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var app = angular.module('app', []);
angular.element(document).ready(function readyHandler() {
angular.bootstrap(document, ['app']);
});
app.service('SettingsService', function() {
return {
'precision' : 2
};
});
app.controller('demo', ['$scope', 'SettingsService', function($scope, settings) {
$scope.settings = settings;
}]);
app.directive('numDisplay', ['SettingsService', function(settings) {
return {
'restrict' : 'EA',
'scope' : {
},
'template' : '<p ng-click="changePrecision()">{{ 123456789 | number:settings.precision }}{{settings.precision}}</p>',
'replace' : true,
'link' : function($scope) {
$scope.settings = settings;
$scope.changePrecision = function(){
$scope.settings.precision++;
};
}
};
}]);

view JSbin

方式三:基于event传播的方式

使用基于event来让控制器跟指令通信,指令中的 scope 就不能设置为独立的了,所以编写指令最好不要使用此方法。

其实跟控制器通信中基于event传播原理是一样,只是把controller中的代码写在了diresctive中的controller中而已。

通过三种方法比较:个人比较推荐方法一中的创建独立scope。因为这样既不会污染其他scope,也能够一眼就能看出来该指令需要从外部scope得到方法或者属性。对于方法二个人觉得用在初始化还是挺不错的。对于方法三则不很不推荐。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var app = angular.module('app', []);
angular.element(document).ready(function readyHandler() {
angular.bootstrap(document, ['app']);
});
// 父scope上的控制器
function demo($scope) {
$scope.send = function() {
$scope.content = 'good!!!';
$scope.$broadcast('send', $scope.content);
};
}
app.directive('chatRoom', [function(settings) {
return {
'restrict' : 'EA',
'template' : '<div><p>XXX: {{content}}</p></div>',
'scope' : true,
'replace' : true,
'controller' : function($scope) {
$scope.$on('chatRoom', function(e, newLocation) {
$scope.content = newLocation;
});
}
};
}]);

view JSbin