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 相关文章推荐
任意位置显示html菜单
Feb 01 Javascript
Mootools 1.2教程(2) DOM选择器
Sep 14 Javascript
两个Javascript小tip资料
Nov 23 Javascript
js 判断文件类型并控制表单提交示例代码
Nov 14 Javascript
jquery+php实现搜索框自动提示
Nov 28 Javascript
由浅入深剖析Angular表单验证
Jul 14 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
Sep 28 Javascript
AngulerJS学习之按需动态加载文件
Feb 13 Javascript
js获取一组日期中最近连续的天数
May 25 Javascript
React学习笔记之条件渲染(一)
Jul 02 Javascript
jQuery实现的简单前端搜索功能示例
Oct 28 jQuery
Angular实现的table表格排序功能完整示例
Dec 22 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 中英文混合排版中处理字符串常用的函数
2007/04/12 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
JavaScript 全面解析各种浏览器网页中的JS 执行顺序
2009/02/17 Javascript
说说掌握JavaScript语言的思想前提想学习js的朋友可以看看
2009/04/01 Javascript
jquery下json数组的操作实现代码
2010/08/09 Javascript
来自国外的14个图片放大编辑的jQuery插件整理
2010/10/20 Javascript
js控制页面控件隐藏显示的两种方法介绍
2013/10/09 Javascript
RequireJS多页面应用实例分析
2016/06/29 Javascript
Highcharts学习之坐标轴
2016/08/02 Javascript
微信小程序左右滑动切换页面详解及实例代码
2017/02/28 Javascript
angular.fromJson与toJson方法用法示例
2017/05/17 Javascript
Angular 通过注入 $location 获取与修改当前页面URL的实例
2017/05/31 Javascript
浅谈关于angularJs中使用$.ajax的注意点
2017/08/12 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
2019/01/29 Javascript
vue把输入框的内容添加到页面的实例讲解
2019/11/11 Javascript
JS图片预加载三种实现方法解析
2020/05/08 Javascript
[03:44]2014DOTA2国际邀请赛 71专访:DK战队赛前讨论视频遭泄露
2014/07/13 DOTA
python正常时间和unix时间戳相互转换的方法
2015/04/23 Python
在Mac OS上部署Nginx和FastCGI以及Flask框架的教程
2015/05/02 Python
python中使用序列的方法
2015/08/03 Python
Python cookbook(数据结构与算法)同时对数据做转换和换算处理操作示例
2018/03/23 Python
浅析Python 引号、注释、字符串
2019/07/25 Python
PyTorch预训练的实现
2019/09/18 Python
如何在Django中使用聚合的实现示例
2020/03/23 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
2020/04/30 Python
详解CSS3 弹性布局快速入门
2019/06/06 HTML / CSS
Hotter Shoes美国官网:英国最受欢迎的舒适鞋
2018/08/02 全球购物
哄娃神器4moms商店:美国婴童用品品牌
2019/03/07 全球购物
Linux文件操作命令都有哪些
2015/02/27 面试题
EJB3.1都有哪些改进
2012/11/17 面试题
申论倡议书范文
2014/05/13 职场文书
2014年教研组工作总结
2014/11/26 职场文书
2014年建筑工作总结
2014/11/26 职场文书
班主任2015新年寄语
2014/12/08 职场文书
结婚幸福感言
2015/08/01 职场文书
mongoDB数据库索引快速入门指南
2022/03/23 MongoDB