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操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
随机推荐
- 数组的创建和各种API
数组的创建方式: 1. 数组直接量 var arr = [] // 创建一个空数组 var arr = [1,2,3,4] // 创建同时初始化元素 2. 实例化对象 var arr=new Arra ...
- Linux的运行级别详细说明
Linux 7个运行级别 # 0 - 停机(千万不要把initdefault设置为0 ) # 1 - 单用户模式 # 2 - 多用户,但是没有NFS # 3 - 完全多用 ...
- Android-第二天(2)
程序3 SimpleAdapter是扩展性最好的适配器,可以定义各种你想要的布局,而且使用很方便 SimpleAdapter(Context context, List<? extends Ma ...
- mybatis_SQL映射(1)
文章摘录自:http://blog.csdn.net/y172158950/article/details/17258377 1. select的映射 <select id="sele ...
- 关于Set<Long>Map<Long,String>的一些小注意事项 自动转换类型
- linux_vi快捷键
vi有哪些快捷方式? 到行头: 0 ^ home 到行尾: $ shif+a(编辑模式) end 退出保存: wq . x .wq!(强制退出保存) 强制退出不保存: q! 光标移到文件最后一行: s ...
- 远程服务调用(RMI)
模块概念的引入,是本框架的一大优势,而跨JVM的远程服务调用则是另一个最有价值的功能. <本地服务调用>一文中我们讲解了跨模块间的服务调用可以是这样的: ServiceHelper.inv ...
- js中常用的方法(数组篇)
1.replace(),根据释义,即为代替,用法为: stringObject.replace(regexp/substr,replacement)括号内前者是待匹配字符串,并用后者代替这个字符串.例 ...
- MOOC网视频下载并视频倍速播放,超简单哒,亲测可用,( •̀ ω •́ )y
由于视频在线播放太卡,想着下载看吧~~可是这个坑爹的网站没有下载按钮,难道就不可以下载视频了吗? 小白不甘心~ 于是动手查了一下,实验很成功,估计如果会爬虫的都不用像我一样一个一个自己去下了,奈何我知 ...
- 重置CentOS 7的Root密码
centos7与centos6有很多修改,不一样了,打算写几篇关于日常用到的改动 修改root密码 centos7的用户模式跟6有所不同 1 - 在启动grub菜单,选择编辑选项启动 2 - 按键盘e ...