对于日常开发中,难免会有controller之间通信需求。对于controller之间通信有两种方式可以做到。

用 Angular 进行开发,基本上都会遇到 Controller 之间通信的问题,本文对此进行一个总结。

在 Angular 中,Controller 之间通信的方式主要有三种:

1)作用域继承。利用子 Controller 控制父 Controller 上的数据。(父 Controller 中的数据要为引用类型,不能是基本类型,原因参见 AngularJS中的作用域 一文)

2)注入服务。把需要共享的数据注册为一个 service,在需要的 Controller 中注入。

3)基于事件。利用 Angular 的事件机制,使用 $on$emit 和 $boardcast

其中,作用域继承仅限于上下级之间的通信,注入服务和基于事件的机制可以实现任意级别的 Controller 通信。

在 这里 可以查看下面栗子的演示。

作用域继承

原理在 作用域 一文中有讲解,这里直接上栗子。

页面:

<div ng-controller="parentCtrl">
<p>data in parent controller : {{data.name}}</p>
<div ng-controller="childCtrl">
<input type="text" ng-model="data.name">
</div>
</div>

控制器:

angular.module('demo', [])

.controller('parentCtrl', ['$scope', function($scope){
$scope.data = {
name: 'htf'
}
}]) .controller('childCtrl', ['$scope', function($scope){ }])

以上是父 Controller 中的数据是引用类型的情况。如果父 Controller 中的数据是基本类型,可通过$scope.$parent.data 访问。

很显然,这种方式仅适用于父子级间 Controller 的通信。

注入服务

在 Angular 中,服务是一个单例,所以在服务中生成一个对象,该对象就可以利用依赖注入的方式在所有的控制器中共享。

看个栗子,先定义一个 service :

angular.module('demo')
.factory('Data', function(){
return {
name: 'htf'
};
})

页面:

<div ng-controller="childCtrl1">
<h3>data in child controller 1 : {{data.name}}</h3>
<input class="form-control" type="text" ng-model="data.name">
</div>
<div ng-controller="childCtrl2">
<h3>data in child controller 2 : {{data.name}}</h3>
<input class="form-control" type="text" ng-model="data.name">
</div>

控制器:

.controller('childCtrl1', ['$scope', 'Data', function($scope, Data){
$scope.data = Data;
}]) .controller('childCtrl2', ['$scope', 'Data', function($scope, Data){
$scope.data = Data;
}])

这种方式适用于任何需要通信的 Controller 之间。

基于事件

Angular 为 $scope 提供了冒泡和隧道机制,$broadcast 会把事件广播给所有子 Controller,而 $emit则会将事件冒泡传递给父 Controller,$on 则是 Angular 的事件监听函数,利用这三者,可以实现上下级和同级(需要构造一个共同的父级 Controller)之间的通信。

上下级之间

这种情况下比较简单。

如果是子 Controller 往父 Controller 上发送事件(从作用域往上发送事件),使用 scope.$emit

$scope.$emit("someEvent", {});

如果是父 Controller 往子 Controller 上发送事件(从作用域往下发送事件),使用 scope.$broadcast

$scope.$broadcast("someEvent", {});

无论是 $emit 还是 $broadcast 发送的事件,都用 $scope.$on 接收:

$scope.$on("someEvent", function(event, data) {
// 这里取到发送过来的数据 data
});

同级之间

同级之间利用事件通信有两种方法。一种是利用上下级之间事件传播的变形,另一种是借助 $rootScope 。

借助父 controller

先看第一种,在子 Controller 中向父 Controller 触发一个事件,然后在父 Controller 中监听事件,再广播给子 Controller ,这样通过事件携带的参数,实现了数据经过父 Controller,在同级 Controller 之间传播。

但是要注意,通过父 Controller 作为中介进行传递的话,子 Controller 触发的事件名和父 Controller 广播用的事件名不能一样,否则会进入死循环。

看代码:

<div ng-controller="outerCtrl">
<h3>data in outer controller: {{name}}</h3>
<div ng-controller="innerCtrl1">
<input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>
<div ng-controller="innerCtrl2">
<input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>
</div>

关键部分在控制器:

.controller('outerCtrl', ['$scope', function($scope){
$scope.name = 'htf';
$scope.$on('dataChanged', function(event, data){
$scope.name = data;
// 2. 父 Ctrl 监听到 dataChanged 时间后,触发 changeData 事件
$scope.$broadcast('changeData', data);
})
}]) .controller('innerCtrl1', ['$scope', function($scope){
$scope.change = function(){
// 1. 子 Ctrl1 中数据改变之后触发 dataChanged 事件
$scope.$emit('dataChanged', $scope.name);
}
$scope.$on('changeData', function(event, data){
$scope.name = data;
})
}]) .controller('innerCtrl2', ['$scope', function($scope){
$scope.change = function(){
$scope.$emit('dataChanged', $scope.name);
}
// 3. 监听到 changeData 事件后,改变子 Ctrl2 中 数据
$scope.$on('changeData', function(event, data){
$scope.name = data;
})
}])

借助 $rootScope

每个 Angular 应用默认有一个根作用域 $rootScope, 根作用域位于最顶层,从它往下挂着各级作用域。

所以,如果子控制器直接使用 $rootScope 广播和接收事件,那么就可实现同级之间的通信。

看栗子:

<div ng-controller="innerCtrlA">
<input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>
<div ng-controller="innerCtrlB">
<input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>

控制器:

.controller('innerCtrlA', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.change = function(){
// 广播事件
$rootScope.$broadcast('nameChanged', $scope.name);
}
$rootScope.$on('nameChanged', function(event, data){
$scope.name = data;
})
}]) .controller('innerCtrlB', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.change = function(){
$rootScope.$broadcast('nameChanged', $scope.name);
}
// 监听事件
$rootScope.$on('nameChanged', function(event, data){
$scope.name = data;
})
}])

参考

  1. 作用域与事件
  2. Angularjs Controller 间通信机制
  3. Communicating Between Controllers In Angular
  4. AngularJS控制器controller如何通信?
  5. controller 间共享数据

angular controller之间通信方式的更多相关文章

  1. angular controller 之间的通信方式

    AngularJS中的controller是个函数,用来向视图的作用域($scope)添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为. 当我们在创建新的控制器时,angularJ ...

  2. AngularJS进阶(九)控制器controller之间如何通信

    AngularJS控制器controller之间如何通信 注:请点击此处进行充电! angular控制器通信的方式有三种: 1,利用作用域继承的方式.即子控制器继承父控制器中的内容 2,基于事件的方式 ...

  3. AngularJS实战之Controller之间的通信

    我们时常会在不同controller之间进行通信,接下来就介绍三种controller之间的通信方式 一.使用$on.$emit和$broadcast进行controller通信 虽然AngularJ ...

  4. angular view之间的数据传递

    之前写过一篇backbone view之间的传递,由于现在在用angular搞开发,现在也来总结一下.在angular 传递数据通俗的讲叫做 广播 ,在一些文章中,也叫做事件的发布与订阅,在angul ...

  5. angularJS中directive与controller之间的通信

    当我们在angularJS中自定义了directive之后需要和controller进行通讯的时候,是怎么样进行通讯呢? 这里介绍3种angular自定义directive与controller通信的 ...

  6. Angular 1与 Angular 2之间的一些差别

    现在在用ng1.5.8做一个项目,ng的优点和特性我就不用多说了,ng1在陆续更新到1.5/1.6后就没再推出新版本了,ng2已经面世测试很久了,如同很多系统和框架一样,每个大的版本更新都会有新特性加 ...

  7. 通过$broadcast或$emit在子级和父级controller之间进行值传递

    通过$broadcast或$emit在controller之间进行值传递,不过这些controller必须是子级或者父级关系, $emit只能向父级parent controller传递事件event ...

  8. AngularJS 中 Controller 之间的通信

    用 Angular 进行开发,基本上都会遇到 Controller 之间通信的问题,本文对此进行一个总结. 在 Angular 中,Controller 之间通信的方式主要有三种: 1)作用域继承.利 ...

  9. angularjs 中使用 service 在controller 之间 share 对象和数据

    在做angularjs 的UI 时,我们经常会遇到一个页面之间有几个controller,在controller 之间share 公共的一些数据和方法就变得比较困难,目前推荐的做法是创建一个servi ...

随机推荐

  1. 调起qq临时通话

    1.在qq推广的网站上的推广工具中将个人或者公司的qq确认为推广qq 2. 选择好显示的图片,将代码拷贝到页面上就可以了

  2. last与lastlog命令

    lastlog 列出所有用户最后登录的时间和登录终端的地址,如果此用户从来没有登录,则显示:**Never logged in**last 列出用户所有的登录时间和登录终端的地址

  3. 模板页 相对路径 JS 加载问题

    问题:我在master页面中引入了如下js文件:<script type="text/javascript" src="http://www.cnblogs.com ...

  4. J2EE项目开发流程简介

    开发流程(一) 提出需求:产品部提出本周期项目的具体需求. 项目计划:项目经理协调开发部.测试部和产品部进行需求协商,产生项目计划. 需求理解:开发部和测试部向产品部提出各自对需求的理解. 产品设计: ...

  5. Spring mvc中@RequestMapping 6个基本用法整理

    继续整理,这个是前段时间用jsp开发的一个站点,说起来php程序员去做jsp程序确实有些小不适应,但是弄完后绝对对于这种强类型语言而比收获还是颇多的. 1,最基本的,方法级别上应用 @RequestM ...

  6. #pragma section

    看了别人使用了#pragma section来共享变量,今天试了下 如下添加代码 #define GLOBAL_SHARED __declspec(allocate(".Shared&quo ...

  7. (原)error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5577534.html 在debug下使用intel的mkl库时(release下无此问题),莫名的出现 ...

  8. asp.net js 获取服务器控件值

    最近在弄js 但是设计到获取服务器控件的值,有点模糊.百度查了资料都达不到效果.现在看看这个,希望朋友们能用上!! <asp:Label ID="lbDepartName" ...

  9. slf4j绑定log4j失败

    1,出现问题的配置 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api< ...

  10. jQuery 改变Form 指向的 Action

    var path = "shiftCancelAction"; $('#queryForm').attr("action",path).submit();