对angularjs框架下controller间的传值方法详解


Posted in Javascript onOctober 08, 2018

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
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进行事件监听。

示例

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上,例如:

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);
}
]);

但是这种方式有点繁琐,定义多个事件处理函数时整个人都不好了,所以我们来改进一下

利用装饰器来定义一个新的事件绑定函数:

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;
}]);
}]);

那么我们在控制器中定义事件处理函数时:

angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);

个人强烈推荐此种做法

第三种方式

利用angularJS中service单例模式的特性,服务(service)提供了一种能在应用的整个生命周期内保持数据的方式,能够在控制器之间进行通信,且能保证数据的一致性。

一般我们都会封装server来为应用提供访问数据的接口,或者跟远程进行数据交互。

示例

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";
}
});

再用简单的方法总结一下

1、父controller,负责监听并广播

//监听:若收到change,把值广播出去
$scope.$on(“change",function (event, msg) {
 $scope.$broadcast(“changeFromBody", msg);
});

2、子controller,负责把变量发给父controller

//向父controller传值$scope.value
 $scope.$emit(“change", $scope.value);

3、子controller,负责监听父controller的广播,给变量赋新值

//监听父controller的广播,得到changeFromBody广播时取$scope.value
$scope.$on(“changeFromBody",function (event, msg) {
 $scope.value = msg;
});

以上这篇对angularjs框架下controller间的传值方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
Nov 11 Javascript
让checkbox不选中即将选中的checkbox不选中
Jul 11 Javascript
javascript复制粘贴与clipboardData的使用
Oct 16 Javascript
jQuery中的编程范式详解
Dec 15 Javascript
js生成随机颜色方法代码分享(三种)
Dec 29 Javascript
微信小程序 支付后台java实现实例
May 09 Javascript
JS获取一个表单字段中多条数据并转化为json格式
Oct 17 Javascript
JS实现将链接生成二维码并转为图片的方法
Mar 17 Javascript
vue 做移动端微信公众号采坑经验记录
Apr 26 Javascript
使用Vuex解决Vue中的身份验证问题
Sep 28 Javascript
Jquery属性的获取/设置及样式添加/删除操作技巧分析
Dec 23 jQuery
Handtrack.js库实现实时监测手部运动(推荐)
Feb 08 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
Oct 08 #Javascript
CKEditor4配置与开发详细中文说明文档
Oct 08 #Javascript
浅谈angularJs函数的使用方法(大小写转换,拷贝,扩充对象)
Oct 08 #Javascript
angularJs复选框checkbox选中进行ng-show显示隐藏的方法
Oct 08 #Javascript
jquery.param()实现数组或对象的序列化方法
Oct 08 #jQuery
angularJs select绑定的model取不到值的解决方法
Oct 08 #Javascript
基于AngularJs select绑定数字类型的问题
Oct 08 #Javascript
You might like
上海地方志办公室-上海电子仪表工业志
2021/03/04 无线电
php实现rc4加密算法代码
2012/04/25 PHP
php获取ip的三个属性区别介绍(HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR)
2012/09/23 PHP
PHPMailer使用教程(PHPMailer发送邮件实例分析)
2012/12/06 PHP
用js实现控制内容的向上向下滚动效果
2007/06/26 Javascript
JS中==与===操作符的比较
2009/03/21 Javascript
firefox事件处理之自动查找event的函数(用于onclick=foo())
2010/08/05 Javascript
用javascript作一个通用向导说明
2011/08/30 Javascript
jquery插件开发方法(初学者)
2012/02/03 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
js AppendChild与insertBefore用法详细对比
2013/12/16 Javascript
JS实现单击输入框弹出选择框效果完整实例
2015/12/14 Javascript
jquery利用json实现页面之间传值的实例解析
2016/12/12 Javascript
基于滚动条位置判断的简单实例
2017/12/14 Javascript
JavaScript面向对象的程序设计(犯迷糊的小羊)
2018/05/27 Javascript
vue路由事件beforeRouteLeave及组件内定时器的清除方法
2018/09/29 Javascript
基于vue+axios+lrz.js微信端图片压缩上传方法
2019/06/25 Javascript
微信小程序如何播放腾讯视频的实现
2019/09/20 Javascript
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
Python3.x爬虫下载网页图片的实例讲解
2018/05/22 Python
python多进程使用及线程池的使用方法代码详解
2018/10/24 Python
快速解决pyqt5窗体关闭后子线程不同时退出的问题
2019/06/19 Python
python两个_多个字典合并相加的实例代码
2019/12/26 Python
python numpy生成等差数列、等比数列的实例
2020/02/25 Python
django haystack实现全文检索的示例代码
2020/06/24 Python
Python confluent kafka客户端配置kerberos认证流程详解
2020/10/12 Python
Python根据URL地址下载文件并保存至对应目录的实现
2020/11/15 Python
Oracle里面常用的数据字典有哪些
2014/02/14 面试题
应届护士推荐信
2013/11/16 职场文书
初中生学习生活的自我评价
2013/11/20 职场文书
代理商会议邀请函
2014/01/27 职场文书
厂长岗位职责
2014/02/19 职场文书
个人四风问题整改措施
2014/10/24 职场文书
2014年教育实习工作总结
2014/11/22 职场文书
RestTemplate如何通过HTTP Basic Auth认证示例说明
2022/03/17 Java/Android
Vue组件化(ref,props, mixin,.插件)详解
2022/05/15 Vue.js