angularjs 控制器、作用域、广播详解
一、控制器
首先列出几种我们平常使用控制器时的几种误区:

我们知道angualrJs中一个控制器时可以对应不同的视图模板的,但这种实现方式存在的问题是:
如果视图1和视图2根本没有任何逻辑关系,这样“控制器”的角色就会很尴尬,因为我们不可能把不同业务的数据模型都绑在同一个控制器中。

这种实现方式也存在一个问题是:如果控制器1和控制器2里面有2个方法是一模一样的怎么办?

<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="CommonController">
<div ng-controller="Controller1">
<p>{{greeting.text}},Angular</p>
<button ng-click="test1()">test1</button>
</div>
<div ng-controller="Controller2">
<p>{{greeting.text}},Angular</p>
<button ng-click="test2()">test2</button>
<button ng-click="commonFn()">通用</button>
</div>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="MVC3.js"></script>
</html>
function CommonController($scope){
$scope.commonFn=function(){
alert("这里是通用功能!");
};
}
function Controller1($scope) {
$scope.greeting = {
text: 'Hello1'
};
$scope.test1=function(){
alert("test1");
};
}
function Controller2($scope) {
$scope.greeting = {
text: 'Hello2'
};
$scope.test2=function(){
alert("test2");
}
}
虽然子级控制器可以继承父级控制器的作用域及方法,但是我们一般不要去这样做,因为很可能会造成作用域的混乱。

正确的方式应该是这样的:我们把公共的方法抽离出来,放在公共的服务当中去,需要的时候从公共的服务中调取就好了。
在使用控制器时要注意几点:
1.不要去复用controller,一个控制器一般只负责一小块视图;(一般控制器处理的都是业务逻辑,业务逻辑的复用性一般很小)
2.不要在controller中操作DOM,这不是控制器的职责;(因为在 controller里面操作DOM会导致浏览器页面的重绘,这种代价是昂贵的)
3.一般不要在控制器里面做数据过滤操作,ng有$filter服务;
一般来说,Controller是不会相互调用的,控制器之间的交互会通过广播事件进行!
二、作用域
angularJs的MVC是借助$scope来实现的!
先来看一段代码:
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="Scope1.css" />
</head>
<body>
<div class="show-scope-demo">
<div ng-controller="GreetCtrl">
Hello {{name}}!
</div>
<div ng-controller="ListCtrl">
<ol>
<li ng-repeat="name in names">
{{name}} from {{department}}
</li>
</ol>
</div>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="Scope1.js"></script>
</html>
function GreetCtrl($scope, $rootScope) {
$scope.name = 'World';
$rootScope.department = 'Angular';
}
function ListCtrl($scope) {
$scope.names = ['Igor', 'Misko', 'Vojta'];
}
上面是两个不同的控制器,尽管ListCtrl控制器里面没有department,但它依然可以访问到department上的变量值。
神奇的$scope
1.$scope是一个对象;
2.$scope是表达式的执行环境(或者叫做作用域)(它是视图和控制器之间的胶水);
3.$scope提供了一些工具方法$watch()/$apply();
(这个是实时检测对象属性变化的,在修改数据时会立刻更新$scope,当$scope发生变化时会立刻重新渲染视图);
(这两个方法虽然提供了监视数据模型变化的能力,将数据模型的变化在整个应用范围内进行通知,但一般我们不太会手动去调用$scope.$apply())
4.$scope是一个树形结构,与DOM标签平行;
5.子$scope会继承父$scope上的属性和方法;
6.每个angularJs应用只有一个$rootScope,一般位于ng-app上,$rootScope是所有$scope的最上层,
($rootScope也是angularJs中最接近全局作用域的对象,在$rootScope上附加太多业务逻辑并不是好主意,这与污染javaScript的全局作用域是一样的)
7.$scope也是实现双向数据绑定的基础;
8.可以用angular.element($0).scope()来进行调试;
9.$scope可以在控制器之间传播事件,可以向上$scope.$emit();也可以向下$scooe.$broadcast();
最后附一张$scope的生命周期图:

创建(创建一个作用域)——链接($scope对象会链接到视图中)——更新(脏值检查)——销毁(销毁作用域)
三、广播
3.1相关概念
通常作用域之间是不共享变量的,但作用域是有层次的,所以我们可以在作用域上通过广播来传递事件。
Angularjs中不同作用域之间可以通过组合使用$emit,$broadcast,,$on的事件广播机制来进行通信
$emit的作用是将事件从子级作用域传播至父级作用域,包括自己,直至根作用域。格式如下:$emit(eventName,args)
$broadcast的作用是将事件从父级作用域传播至子级作用域,包括自己。格式如下:$broadcast(eventName,args)
$on用于在作用域中监控从子级或父级作用域中传播的事件以及相应的数据。格式如下:$on(event,data)
上述说明中,eventName是需要广播的事件的名称,args传递的数据集合,$on 方法中的参数event是事件的相关对象,data是事件传播的数据。

3.2实例说明angularjs $emit $broadcast $on的用法
<div ng-controller="ParentCtrl">
<div ng-controller="SelfCtrl">
<a ng-click="click()">click</a>
<div ng-controller="ChildCtrl"></div>
</div>
<div ng-controller="BroCtrl"></div>
</div>
var appControllers = angular.module('myApp', [])
appControllers.controller('SelfCtrl', ['$scope','$rootScope', function($scope, $rootScope){
var admin1 = {
'name': 'father',
'age': 45
};
var admin2 = {
'name': 'Lucy',
'age': 25
};
$scope.click = function() {
//事件的发送
//向子级控制器传递数据和事件,只有ChildCtrl能接受到广播,还有自己
$scope.$broadcast('to-child', admin2);
//向父级控制器传递数据和事件,只有parentCtrl能接收到广播,还有自己
$scope.$emit('to-parent', admin1);
//$rootScope发出的广播所有的作用域都可以接受到,可以用于同级之间进行广播
$rootScope.$broadcast('to-bro', '平级的数据');
}
}])
appControllers.controller('ParentCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
//事件的接受
$scope.$on('to-parent', function(event, data){
console.log(event);
});
}])
appControllers.controller('ChildCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.$on('to-child', function(event, data){
console.log(data);
});
}])
appControllers.controller('BroCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
//$scope和$rootScope都可以接受到事件
$scope.$on('to-bro', function(event, data){
console.log(data);
});
$rootScope.$on('to-bro', function(event, data){
console.log(data);
});
}]);
angularjs 控制器、作用域、广播详解的更多相关文章
- AngularJS指令进阶 – ngModelController详解
AngularJS指令进阶 – ngModelController详解 在自定义Angular指令时,其中有一个叫做require的字段,这个字段的作用是用于指令之间的相互交流.举个简单的例子,假如我 ...
- angularJS中$apply()方法详解
这篇文章主要介绍了angularJS中$apply()方法详解,需要的朋友可以参考下 对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的 ...
- iOS 视图控制器转场详解
iOS 视图控制器转场详解 前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标有了大幅度的增长,多谢唐巧前辈的推荐.有些人问我相关的问题 ...
- “全栈2019”Java第一百零五章:匿名内部类覆盖作用域成员详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第九十八章:局部内部类访问作用域成员详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Spring MVC 学习)——控制器与@RequestMapping详解
Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解 一.控制器定义 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求 ...
- AngularJS开发指南9:AngularJS作用域的详解
AngularJS作用域是一个指向应用模型的对象.它是表达式的执行环境.作用域有层次结构,这个层次和相应的DOM几乎是一样的.作用域能监控表达式和传递事件. 作用域的特点 作用域提供APIs($wat ...
- AngularJS中transclude用法详解
这篇文章主要介绍了AngularJS中transclude用法,详细分析了transclude的具体功能.使用技巧与相关注意事项,需要的朋友可以参考下 本文实例讲述了AngularJS中transcl ...
- AngularJS开发指南10:AngularJS依赖注入的详解
依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
随机推荐
- Python3 的函数
1.编写power(x,y)函数返回x的y次幂值 def power(x,y): return x**y 2.求最大公约数 def gcd(x,y): r=x%y x=y y=r if r==0: p ...
- django 编程小结
1.增删改查 add obj = Obj(atr=atr..) obj.save() update: __dict__ 遍历 del: 根据id列表删除 query: 首次查询: 直接跳转至页面,前端 ...
- 转载-Linux Shell 数组建立及使用技巧
转载自:http://www.cnblogs.com/chengmo/archive/2010/09/30/1839632.html 如侵犯版权,请联系我删除 linux shell在编程方面比win ...
- JAVA中利用反射机制进行对象和Map相互转换的方法
JAVA的反射机制主要作用是用来访问对象的属性.方法等等.所以,JAVA中对象和Map相互转换可以利用JAVA的反射机制来实现.例子如下: 一.对象转Map的方法 public static Map& ...
- Activity组件安全(下)
什么是Activity劫持 简单的说就是APP正常的Activity界面被恶意攻击者替换上仿冒的恶意Activity界面进行攻击和非法用途.界面劫持攻击通常难被识别出来,其造成的后果不仅会给用户带来严 ...
- 将Flask应用程序部署在nginx,tornado的简单方法
来自:http://www.xuebuyuan.com/618750.html 在网上搜索了一下部署flask应用的方法,大部分是用wsgi部署在nginx上面,部署了很久,都没有成功,可能是我领悟能 ...
- 序列化日期(yyyy-MM-dd hh:mm:ss)
var getDateFormat = function() { var _date = new Date(); //实例化一个Date对象 var _complete = function(valu ...
- linux shell 中的 2>&1 用法说明
linux中有三种标准输入输出,分别是 STDIN,STDOUT,STDERR,对应的数字是 0,1,2. STDIN 是标准输入,默认从键盘读取信息: STDOUT 是标准输出,默认将输出结果输出至 ...
- SQL性能优化的几点建议
1. 索引:索引可以提高查询的速度,但不是使用带有索引的字段查询时,索引都会起作用,如下几种特殊情况下,有可能使用带有索引的字段查询时,索引没有起作用:1)使用LIKE关键字的查询语句 如果匹配字符串 ...
- JAVA动态代理机制解析
1. 概述 首先,我们来思考如下两个问题: 什么是代理模式?为什么要使用代理模式? 简单总结一下,所谓的代理模式就是在原有的服务上多加一个占位,通过这个占位去控制服务的访问.通过代理模式,一方面可以控 ...