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 解决表单仍然提交即使监听处理函数返回false
Mar 14 Javascript
js变量以及其作用域详解
Jul 18 Javascript
js获得鼠标的坐标值的方法
Mar 13 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
Apr 04 Javascript
javascript引用赋值(地址传值)用法实例
Jan 13 Javascript
javascript计时器详解
Feb 28 Javascript
js实现页面跳转的五种方法推荐
Mar 10 Javascript
基于JS代码实现图片在页面中旋转效果
Jun 16 Javascript
AngularJS删除路由中的#符号的方法
Sep 20 Javascript
jQuery实现链接的title快速出现的方法
Feb 20 Javascript
vue实现倒计时功能
Mar 24 Vue.js
JS前端使用Canvas快速实现手势解锁特效
Sep 23 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中进行身份认证
2006/10/09 PHP
php解析html类库simple_html_dom(详细介绍)
2013/07/05 PHP
php导入导出excel实例
2013/10/25 PHP
php实现统计目录文件大小的函数
2015/12/25 PHP
同一个表单 根据要求递交到不同页面的实现方法小结
2009/08/05 Javascript
JavaScript 代码压缩工具小结
2012/02/27 Javascript
jQuery实用基础超详细介绍
2013/04/11 Javascript
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
2013/11/18 NodeJs
JS onmousemove鼠标移动坐标接龙DIV效果实例
2013/12/16 Javascript
jquery和雅虎的yql服务实现天气预报服务示例
2014/02/08 Javascript
浅谈JavaScript的事件
2015/02/27 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
2015/11/06 Javascript
三个js循环的关键字示例(for与while)
2016/02/16 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
JS检测window.open打开的窗口是否关闭
2017/06/25 Javascript
react+ant design实现Table的增、删、改的示例代码
2018/12/27 Javascript
react native 原生模块桥接的简单说明小结
2019/02/26 Javascript
微信小程序实现定位及到指定位置导航的示例代码
2019/08/20 Javascript
JavaScript类的继承多种实现方法
2020/05/30 Javascript
Vue props中Object和Array设置默认值操作
2020/07/30 Javascript
[03:41]2018完美盛典-《Fight With Us》
2018/12/16 DOTA
python实现ID3决策树算法
2017/12/20 Python
Python调用C语言的方法【基于ctypes模块】
2018/01/22 Python
python 给图像添加透明度(alpha通道)
2020/04/09 Python
使用pyecharts1.7进行简单的可视化大全
2020/05/17 Python
纯CSS3实现给头像加个光芒四射且旋转的背景动画效果
2014/05/07 HTML / CSS
CSS3实现时间轴特效
2020/11/02 HTML / CSS
新东方旗下远程教育网站:新东方在线
2020/03/19 全球购物
个人素质的自我评价分享
2013/12/16 职场文书
拖鞋店创业计划书
2014/01/15 职场文书
大学活动总结范文
2014/04/29 职场文书
店长岗位职责
2015/02/11 职场文书
MySQL 全文检索的使用示例
2021/06/07 MySQL
Java并发编程之Executor接口的使用
2021/06/21 Java/Android
Redis源码阅读:Redis字符串SDS详解
2021/07/15 Redis
MySQL事务的ACID特性以及并发问题方案
2022/07/15 MySQL