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 相关文章推荐
JQuery扩展插件Validate 3通过参数设置错误信息
Sep 05 Javascript
封装的jquery翻页滚动(示例代码)
Nov 18 Javascript
String.prototype实现的一些javascript函数介绍
Nov 22 Javascript
jQuery中ztree 点击文本框弹出下拉框的实例代码
Feb 05 Javascript
AngularJS实现表格的增删改查(仅限前端)
Jul 04 Javascript
Angular脚手架开发的实现步骤
Apr 09 Javascript
深入解读Node.js中的koa源码
Jun 17 Javascript
关于layui toolbar和template的结合使用方法
Sep 19 Javascript
在vue-cli中引入lodash.js并使用详解
Nov 13 Javascript
小程序实现录音上传功能
Nov 22 Javascript
VSCode launch.json配置详细教程
Jun 18 Javascript
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 Vue.js
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中的CMS的涵义
2007/03/11 PHP
php合并数组中相同元素的方法
2014/11/13 PHP
php封装的验证码工具类完整实例
2016/10/19 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
jquery之Document元素选择器篇
2008/08/14 Javascript
jquery.artwl.thickbox.js  一个非常简单好用的jQuery弹出层插件
2012/03/01 Javascript
node.js WEB开发中图片验证码的实现方法
2014/06/03 Javascript
js中运算符&amp;&amp; 和 || 的使用记录
2014/08/21 Javascript
jQuery制作简洁的图片轮播效果
2015/04/03 Javascript
js如何实现点击标签文字,文字在文本框出现
2015/08/05 Javascript
JS添加或修改控件的样式(Class)实现方法
2016/10/15 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
JS通过调用微信API实现微信支付功能的方法示例
2017/06/29 Javascript
js+html5实现复制文字按钮
2017/07/15 Javascript
Vue-cli打包后如何本地查看的操作
2020/09/02 Javascript
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
python编写暴力破解FTP密码小工具
2014/11/19 Python
windows下python之mysqldb模块安装方法
2017/09/07 Python
Python实现的维尼吉亚密码算法示例
2018/04/12 Python
详解python如何在django中为用户模型添加自定义权限
2018/10/15 Python
Python eval的常见错误封装及利用原理详解
2019/03/26 Python
Python matplotlib 绘制双Y轴曲线图的示例代码
2020/06/12 Python
HTML5在IE10、火狐下中文乱码问题的解决方法
2013/11/18 HTML / CSS
将SVG图引入到HTML页面的实现
2019/09/20 HTML / CSS
Subside Sports德国:足球球衣和球迷商品
2019/06/08 全球购物
斯洛伐克香水和化妆品购物网站:Parfemy-Elnino.sk
2020/01/28 全球购物
什么是Smarty变量操作符?如何使用Smarty变量操作符
2014/07/18 面试题
给男朋友的道歉信
2014/01/12 职场文书
期末自我鉴定
2014/02/02 职场文书
在职员工证明书
2014/09/19 职场文书
小学生安全教育广播稿
2014/10/20 职场文书
淘宝文案策划岗位职责
2015/04/14 职场文书
工作年限证明范本
2015/06/15 职场文书
MySQL对数据表已有表进行分区表的实现
2021/11/01 MySQL
Vue3中的Refs和Ref详情
2021/11/11 Vue.js
idea下配置tomcat避坑详解
2022/04/12 Servers