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 相关文章推荐
你的编程语言可以这样做吗?
Sep 07 Javascript
Ajax,UTF-8还是GB2312 eval 还是execScript
Nov 13 Javascript
3种Jquery限制文本框只能输入数字字母的方法
Dec 03 Javascript
jQuery使用load()方法载入另外一个网页文件内的指定标签内容到div标签的方法
Mar 25 Javascript
超详细的javascript数组方法汇总
Nov 21 Javascript
jQuery实现弹出窗口弹出div层的实例代码
Jan 09 Javascript
vue-cli axios请求方式及跨域处理问题
Mar 28 Javascript
vue中如何实现后台管理系统的权限控制的方法示例
Sep 19 Javascript
vue-cli3使用 DllPlugin 实现预编译提升构建速度
Apr 24 Javascript
vue集成kindeditor富文本的实现示例代码
Jun 07 Javascript
使用vscode快速建立vue模板过程详解
Oct 10 Javascript
JS常用跨域方法实现原理解析
Dec 09 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
3个PHP多维数组转为一维数组的方法实例
2014/03/13 PHP
高性能PHP框架Symfony2经典入门教程
2014/07/08 PHP
PHP实现双链表删除与插入节点的方法示例
2017/11/11 PHP
编写跨浏览器的javascript代码必备[js多浏览器兼容写法]
2008/10/29 Javascript
javascript 禁止复制网页
2009/06/11 Javascript
node.js中的fs.closeSync方法使用说明
2014/12/17 Javascript
javascript父子页面通讯实例详解
2015/07/17 Javascript
JavaScript与HTML的结合方法详解
2015/11/23 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
2015/12/23 Javascript
jQuery图片轮播插件——前端开发必看
2016/05/31 Javascript
使用plupload自定义参数实现多文件上传
2016/07/19 Javascript
jQuery右下角悬浮广告实例
2016/10/17 Javascript
JS限定手机版中图片大小随分辨率自动调整的方法
2016/12/05 Javascript
js return返回多个值,通过对象的属性访问方法
2017/02/21 Javascript
node.js实现登录注册页面
2017/04/08 Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
2018/10/31 Javascript
简单了解JavaScript中常见的反模式
2019/06/21 Javascript
Javascript执行流程细节原理解析
2020/05/14 Javascript
在Python中使用第三方模块的教程
2015/04/27 Python
浅谈python字符串方法的简单使用
2016/07/18 Python
Python开发中爬虫使用代理proxy抓取网页的方法示例
2017/09/26 Python
win10下Python3.6安装、配置以及pip安装包教程
2017/10/01 Python
python获取文件路径、文件名、后缀名的实例
2018/04/23 Python
python实现黑客字幕雨效果
2018/06/21 Python
Python Learning 列表的更多操作及示例代码
2018/08/22 Python
python opencv 简单阈值算法的实现
2019/08/04 Python
Python xlwt模块使用代码实例
2020/06/10 Python
微软俄罗斯官方网站:Microsoft俄罗斯
2016/09/18 全球购物
Amara德国:家居饰品、设计师品牌和豪华礼品
2019/05/20 全球购物
后勤副校长自我鉴定
2013/10/13 职场文书
大学三年计划书范文
2014/04/30 职场文书
流动人口婚育证明
2014/10/19 职场文书
三方股东合作协议书
2014/10/28 职场文书
群众路线学习心得体会范文
2014/11/05 职场文书
辩护词范文大全
2015/05/21 职场文书
小学生优秀作文范文(六篇)
2019/07/10 职场文书