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 相关文章推荐
JQuery 获取和设置Select选项的代码
Feb 07 Javascript
围观tangram js库
Dec 28 Javascript
jQuery EasyUI API 中文文档 - Calendar日历使用
Oct 19 Javascript
javascript修改表格背景色实例代码分享
Dec 10 Javascript
node中socket.io的事件使用详解
Dec 15 Javascript
angular4模块中给标签添加背景图的实现方法
Sep 15 Javascript
使用socket.io制做简易WEB聊天室
Jan 02 Javascript
解决vue打包css文件中背景图片的路径问题
Sep 03 Javascript
bootstrap table合并行数据并居中对齐效果
Oct 17 Javascript
详解vue页面首次加载缓慢原因及解决方案
Nov 06 Javascript
vue swipeCell滑动单元格(仿微信)的实现示例
Sep 14 Javascript
JS + HTML 罗盘式时钟的实现
May 21 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
修改php.ini实现Mysql导入数据库文件最大限制的修改方法
2007/12/11 PHP
php编程实现获取excel文档内容的代码实例
2011/06/28 PHP
基于jquery的超简单上下翻
2010/04/20 Javascript
js在指定位置增加节点函数insertBefore()用法实例
2015/01/12 Javascript
超详细的javascript数组方法汇总
2015/11/21 Javascript
AngularJs Understanding the Controller Component
2016/09/02 Javascript
JavaScript中Number对象的toFixed() 方法详解
2016/09/02 Javascript
ES6学习笔记之Set和Map数据结构详解
2017/04/07 Javascript
vue单页应用中如何使用jquery的方法示例
2017/07/27 jQuery
JavaScript实现无刷新上传预览图片功能
2017/08/02 Javascript
利用javascript如何随机生成一定位数的密码
2017/09/22 Javascript
基于vue1和vue2获取dom元素的方法
2018/03/17 Javascript
小程序的上传文件接口的注意要点解析
2019/09/17 Javascript
JavaScript实现拖拽功能
2020/02/11 Javascript
深入浅析JavaScript中的in关键字和for-in循环
2020/04/20 Javascript
[03:12]完美世界DOTA2联赛PWL DAY6集锦
2020/11/05 DOTA
Python 文件重命名工具代码
2009/07/26 Python
python中正则表达式与模式匹配
2019/05/07 Python
Python Web版语音合成实例详解
2019/07/16 Python
Python中利用LSTM模型进行时间序列预测分析的实现
2019/07/26 Python
vscode 配置 python3开发环境的方法
2019/09/19 Python
Python数据持久化存储实现方法分析
2019/12/21 Python
django处理select下拉表单实例(从model到前端到post到form)
2020/03/13 Python
Python要求O(n)复杂度求无序列表中第K的大元素实例
2020/04/02 Python
Python实现将元组中的元素作为参数传入函数的操作
2020/06/05 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
python中upper是做什么用的
2020/07/20 Python
用python对excel查重
2020/12/07 Python
俄罗斯美容和健康网上商店:Созвездие Красоты
2019/07/23 全球购物
高中自我鉴定
2013/12/20 职场文书
九年级英语教学反思
2014/01/31 职场文书
《记金华的双龙洞》教学反思
2014/04/19 职场文书
纪念九一八事变演讲稿:青少年应树立远大理想
2014/09/14 职场文书
2014年优秀党员材料
2014/12/18 职场文书
物业前台接待岗位职责
2015/04/03 职场文书
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python