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动态调整iframe高度的方法
Mar 06 Javascript
JavaScript中SQL语句的应用实现
May 04 Javascript
javascript中全局对象的isNaN()方法使用介绍
Dec 19 Javascript
IE6已终止操作问题的2种情况及解决
Apr 23 Javascript
jquery实现显示已选用户
Jul 21 Javascript
node中socket.io的事件使用详解
Dec 15 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
Apr 03 jQuery
koa上传excel文件并解析的实现方法
Aug 09 Javascript
jQuery实现鼠标移入移出事件切换功能示例
Sep 06 jQuery
15分钟深入了解JS继承分类、原理与用法
Jan 19 Javascript
extjs图形绘制之饼图实现方法分析
Mar 06 Javascript
vue实现员工信息录入功能
Jun 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
WordPress用户登录框密码的隐藏与部分显示技巧
2015/12/31 PHP
json跟xml的对比分析
2008/06/10 Javascript
从零开始学习jQuery (四) jQuery中操作元素的属性与样式
2011/02/23 Javascript
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
JS过滤url参数特殊字符的实现方法
2013/12/24 Javascript
JQuery动画animate的stop方法使用详解
2014/05/09 Javascript
js实现的牛顿摆效果
2015/03/31 Javascript
JavaScript基于ajax编辑信息用法实例
2015/07/15 Javascript
jQuery EasyUI 入门必看
2016/06/03 Javascript
JS实现添加,替换,删除节点元素的方法
2016/06/30 Javascript
jquery 实现回车登录详解及实例代码
2016/10/23 Javascript
jQuery Jsonp跨域模拟搜索引擎
2017/06/17 jQuery
vue 双向数据绑定的实现学习之监听器的实现方法
2018/11/30 Javascript
详解vue中在循环中使用@mouseenter 和 @mouseleave事件闪烁问题解决方法
2020/04/07 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
JavaScript 获取滚动条位置并将页面滑动到锚点
2021/02/08 Javascript
Python中使用glob和rmtree删除目录子目录及所有文件的例子
2014/11/21 Python
python 保存float类型的小数的位数方法
2018/10/17 Python
用python 实现在不确定行数情况下多行输入方法
2019/01/28 Python
django框架F&amp;Q 聚合与分组操作示例
2019/12/12 Python
python默认参数调用方法解析
2020/02/09 Python
Python对称的二叉树多种思路实现方法
2020/02/28 Python
Python分析最近大火的网剧《隐秘的角落》
2020/07/02 Python
python dict如何定义
2020/09/02 Python
高清安全摄像头系统:Lorex Technology
2018/07/20 全球购物
测绘工程本科生求职信
2013/10/10 职场文书
材料员岗位职责
2014/03/13 职场文书
担保书格式
2015/01/20 职场文书
2015年社区民政工作总结
2015/04/21 职场文书
入党介绍人意见2015
2015/06/01 职场文书
学习习近平主席讲话心得体会
2016/01/20 职场文书
汽车销售合同文本
2019/08/08 职场文书
导游词之贵州织金洞
2019/10/12 职场文书
SQL实现LeetCode(197.上升温度)
2021/08/07 MySQL
Python装饰器的练习题
2021/11/23 Python
Golang 入门 之url 包
2022/05/04 Golang