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 相关文章推荐
表单提交验证类
Jul 14 Javascript
jQuery formValidator表单验证插件开源了 含API帮助、源码、示例
Aug 14 Javascript
jQuery Validation实例代码 让验证变得如此容易
Oct 18 Javascript
jquery的each方法使用示例分享
Mar 25 Javascript
javascript中使用正则计算中文长度的例子
Apr 29 Javascript
jquery attr方法获取input的checked属性问题
May 26 Javascript
JavaScript比较两个对象是否相等的方法
Feb 06 Javascript
移动端H5开发 Turn.js实现很棒的翻书效果
Jun 20 Javascript
jQuery快速高效制作网页交互特效
Feb 24 Javascript
Angular.js中数组操作的方法教程
Jul 31 Javascript
vue.js element-ui validate中代码不执行问题解决方法
Dec 18 Javascript
antd Upload 文件上传的示例代码
Dec 14 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
JavaScript 替换Html标签实现代码
2009/10/14 Javascript
jQuery学习笔记之jQuery选择器的使用
2010/12/22 Javascript
jQuery1.6 正式版发布并提供下载
2011/05/05 Javascript
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
2011/09/22 Javascript
js实现数组去重、判断数组以及对象中的内容是否相同
2013/11/29 Javascript
jquery中html、val与text三者属性取值的联系与区别介绍
2013/12/29 Javascript
jQuery 过滤方法filter()选择具有特殊属性的元素
2014/06/15 Javascript
jQuery中unbind()方法用法实例
2015/01/19 Javascript
javascript实现捕捉键盘上按下的键
2015/05/05 Javascript
jquery实现的蓝色二级导航条效果代码
2015/08/24 Javascript
图片旋转、鼠标滚轮缩放、镜像、切换图片js代码
2020/12/13 Javascript
快速掌握Node.js事件驱动模型
2016/03/21 Javascript
简单总结JavaScript中的String字符串类型
2016/05/26 Javascript
Angular 页面跳转时传参问题
2016/08/01 Javascript
JavaScript数据结构与算法之二叉树添加/删除节点操作示例
2019/03/01 Javascript
node.js实现微信开发之获取用户授权
2019/03/18 Javascript
vue-video-player 解决微信自动全屏播放问题(横竖屏导致样式错乱问题)
2020/02/25 Javascript
Openlayers学习之加载鹰眼控件
2020/09/28 Javascript
微信小程序实现弹幕墙(祝福墙)
2020/11/18 Javascript
手写Vue源码之数据劫持示例详解
2021/01/04 Vue.js
[01:14:19]NAVI vs Mineski 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
python网络编程学习笔记(三):socket网络服务器
2014/06/09 Python
python进程类subprocess的一些操作方法例子
2014/11/22 Python
django实现类似触发器的功能
2019/11/15 Python
Gap工厂店:Gap Factory
2017/11/02 全球购物
荷兰游戏商店:Allyouplay
2019/03/16 全球购物
学生出入校管理制度
2014/01/16 职场文书
物流管理专业毕业生求职信
2014/03/23 职场文书
留守儿童工作方案
2014/06/02 职场文书
少先队工作总结2015
2015/05/13 职场文书
2019安全宣传标语大全
2019/08/14 职场文书
创业计划书之养殖业
2019/10/11 职场文书
个人销售励志奋斗口号
2019/12/05 职场文书
python将图片转为矢量图的方法步骤
2021/03/30 Python
SQLServer 日期函数大全(小结)
2021/04/08 SQL Server
Redis高可用集群redis-cluster详解
2022/03/20 Redis