AngularJS控制器controller正确的通信的方法


Posted in Javascript onJanuary 25, 2016

AngularJS是一款非常强大的前端MVC框架,AngularJS中的controller是个函数,用来向视图的作用域($scope)添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为。

当我们在创建新的控制器时,angularJS会帮我们生成并传递一个新的$scope对象给这个controller,在angularJS应用的中的任何一个部分,都有父级作用域的存在,顶级就是ng-app所在的层级,它的父级作用域就是$rootScope。

每个$scope的$root指向$rootScope, $cope.$parent指向父级作用域。

cotroller之间的通信本质上是当前的controller所在的$scope如何跟其他controller上的$scope进行通信。

通常有3中解决方式:

利用作用域继承的原理,子控制器访问父级控制器中的内容。 使用angularJS中的事件,也就是使用$on,$emit,$broadcast进行消息传递 使用angularJS中的服务
第一种方式

即作用域嵌套作用域,有一定的使用限制,需要作用域嵌套起来,在实际开发中这种场景相对比较少,但也不是没有,这种方式更简单直接。

angularJS中默认情况下,当前作用域中无法找到某个属性时,就会在父级作用域中进行查找,若找不到直至查找到$rootScope。 如果在$rootScope中也无法找到程序依旧运行,但视图不会更新。

示例

javascript

//Javascript
app.controller('ParentController', function($scope) { 
$scope.person = {greeted: false};
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.person.name = 'Ari Lerner';
};
});
//HTML
<div ng-controller="ParentController">
<div ng-controller="ChildController">
<a ng-click="sayHello()">Say hello</a>
</div>
{{ person }}
</div>
//result
{"greeted":true, "name": "Ari Lerner"}

第二种方式

因为作用域是有层次的,所以可以利用作用域链传递事件。

传递事件有2种方式: * $broadcast: 触发的事件要通知整个事件系统(允许任意作用域处理这个事件)就要向下传播。 * $emit: 如果要提醒一个全局模块,需要通知更高层次的作用域时(例如$rootscope)需要把事件向上传递。

作用域上使用$on进行事件监听。

示例

JavaScript

app.controller('ParentController', function($scope) { 
$scope.$on('$fromSubControllerClick', function(e,data){
console.log(data); // hello
});
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.$emit('$fromSubControllerClick','hello');
};
});
//HTML
<div ng-controller="ParentController">
<div ng-controller="ChildController">
<a ng-click="sayHello()">Say hello</a>
</div>
</div>

在这里想要说的另外一个问题就是事件传播的性能问题,$broadcast+$on的方式回通知所有的子作用域,这里就会有性能问题,所以推荐使用$emit+$on的方式,为了进一步提升性能,定义的事件处理函数要在作用域销毁时一起释放掉。

使用$emit+$on的方式需要我们将事件监听绑定在$rootScope上,例如:

JavaScript

angular
.module('MyApp')
.controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) {
var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
console.log('foo');
});
$scope.$on('$destroy', unbind);
}
]);

但是这种方式有点繁琐,定义多个事件处理函数时整个人都不好了,所以我们来改进一下

利用装饰器来定义一个新的事件绑定函数:

JavaScript

angular
.module('MyApp')
.config(['$provide', function($provide){
$provide.decorator('$rootScope', ['$delegate', function($delegate){
Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
value: function(name, listener){
var unsubscribe = $delegate.$on(name, listener);
this.$on('$destroy', unsubscribe);
return unsubscribe;
},
enumerable: false
});
return $delegate;
}]);
}]);

那么我们在控制器中定义事件处理函数时:

JavaScript

angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);

个人强烈推荐此种做法

第三种方式

利用angularJS中service单例模式的特性,服务(service)提供了一种能在应用的整个生命周期内保持数据的方式,能够在控制器之间进行通信,且能保证数据的一致性。

一般我们都会封装server来为应用提供访问数据的接口,或者跟远程进行数据交互。

示例

JavaScript

var myApp = angular.module("myApp", []);
myApp.factory('Data', function() {
return {
name: "Ting"
}
});
myApp.controller('FirstCtrl', function($scope, Data) {
$scope.data = Data;
$scope.setName = function() {
Data.name = "Jack";
}
});
myApp.controller('SecondCtrl', function($scope, Data) {
$scope.data = Data;
$scope.setName = function() {
Data.name = "Moby";
}
});

以上所述是针对AngularJS控制器controller正确的通信的方法,希望能够帮助到大家。

Javascript 相关文章推荐
JavaScript asp.net 获取当前超链接中的文本
Apr 14 Javascript
js css样式操作代码(批量操作)
Oct 09 Javascript
比较搞笑的js陷阱题
Feb 07 Javascript
js动态拼接正则表达式的两种方法
Mar 04 Javascript
JavaScript控制图片加载完成后调用回调函数的方法
Mar 20 Javascript
jQuery插件ajaxFileUpload实现异步上传文件效果
Apr 14 Javascript
jQuery实现多级联动下拉列表查询框
Jan 18 Javascript
基于gulp合并压缩Seajs模块的方式说明
Jun 14 Javascript
浅谈javascript中关于日期和时间的基础知识
Jul 13 Javascript
AjaxUpLoad.js实现文件上传
Mar 05 Javascript
element-ui 中的table的列隐藏问题解决
Aug 24 Javascript
vue1.0和vue2.0的watch监听事件写法详解
Sep 11 Javascript
AngularJS入门心得之directive和controller通信过程
Jan 25 #Javascript
详解jquery事件delegate()的使用方法
Jan 25 #Javascript
AngularJS中的Directive实现延迟加载
Jan 25 #Javascript
AngularJS中的Directive自定义一个表格
Jan 25 #Javascript
理解JavaScript事件对象
Jan 25 #Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
Jan 25 #Javascript
学习JavaScript事件流和事件处理程序
Jan 25 #Javascript
You might like
SONY ICF-F10中波修复记
2021/03/02 无线电
PHP中路径问题的解决方案
2006/10/09 PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
PHP图片等比例缩放生成缩略图函数分享
2014/06/10 PHP
用 Composer构建自己的 PHP 框架之使用 ORM
2014/10/30 PHP
php多个文件及图片上传实例详解
2014/11/10 PHP
php计算税后工资的方法
2015/07/28 PHP
给PHP开发者的编程指南 第一部分降低复杂程度
2016/01/18 PHP
phpinfo() 中 Local Value(局部变量)Master Value(主变量) 的区别
2016/02/03 PHP
PHP将页面中点击数量高的链接进行高亮显示的方法
2016/05/30 PHP
js压缩利器
2007/02/20 Javascript
js 固定悬浮效果实现思路代码
2013/08/02 Javascript
node.js中的events.emitter.listeners方法使用说明
2014/12/10 Javascript
js实现每日自动换一张图片的方法
2015/05/04 Javascript
深入浅出理解JavaScript高级定时器原理与用法
2018/08/02 Javascript
小程序点赞收藏功能的实现代码示例
2018/09/07 Javascript
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
中高级前端必须了解的JS中的内存管理(推荐)
2019/07/04 Javascript
浅谈Layui的eleTree树式选择器使用方法
2019/09/25 Javascript
Vue 一键清空表单的实现方法
2020/02/07 Javascript
JS判断浏览器类型与操作系统的方法分析
2020/04/30 Javascript
Vue自定义render统一项目组弹框功能
2020/06/07 Javascript
Python Deque 模块使用详解
2014/07/04 Python
一些常用的Python爬虫技巧汇总
2016/09/28 Python
Python爬虫之正则表达式基本用法实例分析
2018/08/08 Python
python在回调函数中获取返回值的方法
2019/02/22 Python
python实现输出一个序列的所有子序列示例
2019/11/18 Python
英国最出名高街品牌:Forever Unique
2018/02/24 全球购物
加拿大在线隐形眼镜和眼镜店:VisionPros
2019/10/06 全球购物
对于没有初始化的变量的初始值可以作怎样的假定
2014/10/12 面试题
流动人口婚育证明
2014/10/19 职场文书
体育教师个人工作总结
2015/02/09 职场文书
父亲节感言
2015/08/03 职场文书
幼儿园小班班务总结
2015/08/03 职场文书
python数据库批量插入数据的实现(executemany的使用)
2021/04/30 Python
win10搭建配置ftp服务器的方法
2022/08/05 Servers