AngularJS 学习笔记-第一章:速成
来源:互联网 发布:集金号软件下载 编辑:程序博客网 时间:2024/06/05 08:55
本文章是针对于刚开始学习angularJS的菜鸟们,根据(精通angularJS一书)做的精简版读书笔记, 旨在通过笔记让更多的前端开发,在一周之内可以入门AngularJS。
第一章 速成
- 1.快速使用
- a.导入angularJS 库文件 (线上库或者离线库都可以,如果本地测试建议使用离线库,因为速度不是快一点点哦)
- b.在html或者body DOM标签上添加 ng-app,表示这是一个angularJS的应用
- c.初始化一个模型,并使用。ng-init初始化模型,并通过表达式 {{name}}传递值
<!DOCTYPE html><html><head> <title></title> <!-- 线上版本:https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js 脱机版本,请从https://angularjs.org/ 下载angular.js并且放在html用目录下 --> <script type="text/javascript" src='angular.js'></script></head><body ng-app ng-init="name='World'"><!-- input 的改变会直接反应在 下面的<p>--> <input type="text" name="" ng-model="name"> <p>Hello, {{name}}</p></body></html>
hello world的例子没有明显的分层策略:数据初始化、逻辑和视图都混在了同一个文件中。通常情况我们希望把逻辑控制放倒一个controller里(ng-controller)来取而代之ng-init
<!DOCTYPE html><html><head> <title></title> <script type="text/javascript" src='angular.js'></script> <script type="text/javascript"> // 1.3.0-beta.15 以后的版本不能直接定义controller,必须先定义model,再注入controller var myModel = angular.module('myapp1', []).controller('myController', function($scope) { $scope.name = 'eric';//$scope对象是末班的域模型 }); </script></head><!-- 必须要声明ng-app,不能使用匿名。myApp1对应于module名字--><body ng-app='myapp1'> <div ng-controller="myController"> <input type="text" name="" ng-model="name"> <p>Hello, {{name}}</p> </div></body></html>
2.作用域层级
每个$scope都是Scope类实例,$scope类拥有很多方法,用于控制作用域的生命周期、提供事件传播功能,一级支持模板的渲染等。
function($scope){} 只有参数,它是从何而来呢?
答案是ng-controller指令会去调用scope对象的$new()方法创建新的作用域$scope。看上去需要至少一个作用域实例才能创建新的作用域。确实如此,AngularJS拥有$rootScope,它是其他所有作用域的父作用域,将在新应用启动时自动创建
ng-controller指令是作用域创建指令,DOM树中遇到作用域创建指令时,AngularJS都会闯将Scope类的新实例$scope,新创建的$scope会拥有$parent属性,并指向它的父作用域。
某些指令会创建子作用域,如ng-repeat,对应每个country都有个新变量要暴露给$scope而且不能覆盖之前变量的值。AngularJS为了解决此问题,给集合中每个元素创建新的作用域。这些作用域会组成类似DOM树 层级结构,用Chrome的插件Batarang可以查看
<!DOCTYPE html><html><head> <title></title> <script type="text/javascript" src="angular.js"></script> <script type="text/javascript"> angular.module('myApp', []).controller('myController', function($scope) { $scope.countries = [{ name: '中国', population: '13亿' }, { name: '日本', population: '1亿' }]; }); </script></head><body ng-app='myApp'> <div ng-controller='myController'> <ul> <li ng-repeat='country in countries'> {{country.name}} has {{country.population}} </li> </ul> </div></body></html>
作用域中定义的属性对所有子作用域是可见的,只要子作用域没有定义同名属性。AngularJS中的作用域继承和Javascript的原型继承遵循同样的规则(沿继承树向上查找属性,直到倒找为止)。
在进行read access的时候作用域层级的继承关系直观易懂。然而,进行write access是的情况就有些复杂了。访问父作用域的属性,就必须使用
推荐解决方案是将变量绑定为某个对象的属性,而不是直接绑定作用域的属性。如:
<!--错误的方式,子作用域的name和父作用域冲突覆盖之--><body ng-app='myapp1' ng-init="name='world'"> <h1>{{name}}</h1> <div ng-controller="myController"> <input type="text" name="" ng-model="name"> <p>Hello, {{name}}</p> </div></body><!--正确的方式--><body ng-app='myapp1' ng-init="thing={name:'world'}"> <h1>{{thing.name}}</h1> <div ng-controller="myController"> <input type="text" name="" ng-model="thing.name"> <p>Hello, {{thing.name}}</p> </div></body>
作用域通常在不需要的时候会被销毁(垃圾回收),也可以通过调用Scope类上的
3.事件系统
事件可以从任何作用域开始分发(dispatch)。然后向上分发(
AngularJS的核心服务与指令通过这趟事件列车来发送信号,通知应用状态的重要变化。例如,可以监听$locationChangeSuccess事件(由4rootDvope广播),当浏览器url变化时我们可以收到如下通知。
$scope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl){//做出相应变化});//$on方法,用于注册作用域事件的处理器。与DOM事件一样event对象有preventDefault()和stopPropagation()方法。
AngularJS中,仅有三个事件可以被向上分发(emitted)
- $includeContentRequested
- $includeContentLoaded
- $viewContentLoaded
七个事件可以被向下广播(broadcasted) - $locationChangeStart
- $locationChangeSuccess
- $routeUpdate
- $routeChangeStart
- $routChangeSuccess
- $routeChangeError
- $destroy
4.模块与依赖注入
全局定义的控制器构造函数,只在简单代码示例和快速制作原型时才有用,永远不要在复杂的真是应用中使用全局定义的控制器。
让我们看看如何将丑陋的,全局定义的控制器模块化:
//模块化之前,mycontroller是全局函数 var mycontroller = function($scope) { $scope.name = 'eric'; } //模块化之后,mycontroller只应用于ng-app=‘myapp1’的模块 var myModel = angular.module('myapp1', []).controller('myController', function($scope) { $scope.name = 'eric'; });
依赖注入第一步,是将对象注册在module上,我们不直接注册对象的实例,而是将对象创建的方案抛给依赖注入系统,而后AngularJS解释这些方案以初始化对象,并在之后连接它们,最后成为可运行的应用。
AngularJS的
$injector服务创建的对象称之为服务(service)。在整个应用的生命中,每种方案AngularJS仅解释一次,也就是说,每个对象仅有一个实例。
原型继承
var NotificationService = function (){ this.MAX_LEN = 10; this.notificationsArchive = new NotificationsArchive(); this.notifications = []; }; NotificationService.prototype.push = function(notification){ var newLen, notificationToArchive; newLen = this.notification.unshift(notification);//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。 if(newLen > this.MAX_LEN){ notificationToArchive = this.notifications.pop(); this.notificationsArchive.archive(notificationToArchive); } }; NotificationService.prototype.getCurrent = function(){ return this.notification; };
Value注册
注册已经初始化好的对象,缺点是被注册的值必须是已经实例化好,并且不依赖于其他对象的
//angularJS值(value)注入 var myapp1 = angualr.module('myapp1',[]); myapp1.value('notificationsArchive', new NotificationsArchive());
Service注册
NotificationService依赖于notificationsArchive,所以他不能注册为值对象,
//angularJS(serivce)服务注入,通过依赖注入,在NotificationService构造函数中可以消除new关键字,意味着此服务已经不依赖于其他对象的初始化,可以接受哦任何归档服务,这让应用变得非常灵活。 myapp1.service('notificationService',NotificationService); //NotificationService构造函数 var NotificationService = function(notificationsArchive){ this.notificationsArchive = notificationsArchive; }
Factory注册
另一条注册对象创建方案的途径是使用factory方法,任何能够创建对象的函数都可以被注册,因此它想必service而言更加灵活。factory是让对象加入依赖注入系统最常用的方法,它十分灵活,又能实现复杂的对象创建逻辑。
myapp1.factory('NotificationService', function(notificationsArchive) { this.MAX_LEN = 10; this.notifications = []; var ret = { push: function(notification) { var newLen, notificationToArchive; newLen = this.notification.unshift(notification); //unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。 if (newLen > this.MAX_LEN) { notificationToArchive = this.notifications.pop(); notificationsArchive.archive(notificationToArchive); } }, getCurrent: function() { return this.notification; } } });
constant注册
//理想状态下应该这样子获取配置,而不是写死在函数中myapp1.factory('NotificationService', function(notificationsArchive, MAX_LEN) {...});myapp1.constant('MAX_LEN', 10);
Provider
以上所有注册方法,都是最通用方法provider的特殊类型,下面是provider注册notificationsService的例子
//provider是一个函数,它返回包含$get属性的对象,改属性是一个工厂函数,它被调用时会返回service的实例,在$get方法被调用前,还能设置配置信息。实际上,我们能够设置maxLen myapp1.provider('notificationsService', function() { var config = { maxLen: 10 }; var notifications = []; return { setMaxLen: function(max) { config.maxLen = max || config.maxLen; }, $get: function(notificationsArchive) { return { { push: function(notification) { var newLen, notificationToArchive; newLen = this.notifications.unshift(notification); //unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。 if (newLen > config.MAX_LEN) { notificationToArchive = this.notifications.pop(); notificationsArchive.archive(notificationToArchive); } }, getCurrent: function() { return this.notification; } } } } } });
模块的生命周期
如前所属,angularJS支持多装对象创建方案,provider是其中的通用方法,它在创建对象实例前可以对其进行配置。为了支持provider,angularJS将模块生命周期分为两个阶段,
1. 配置阶段
2. 运行阶段
//这里config对notificationServiceProvider有依赖,表明他是即将执行的对象创建方案,配置阶段允许我们对他进行最后的调整myapp1.config(function(notificationSerivceProvider){ notificationSerivceProvider.setMaxLen(5);});
//为了说明运行阶段的作用,我们假设要显示应用的已运行时间给用户。为了实现目标,我们将应用的已运行事假定义为$rootScope实例的属性,代码如下:myapp1.run(function($rootScope){ $rootScope.appstart = new Date();})
模块的生命周期
模块依赖注入
//通知服务和归档服务,可以迁移到它们自己的模块中去(分别命名为notifications和archive)angular.module('application',['notifications','archive'])
跨模块的可见性
1. 定义在子模块的服务可以注入父模块
angular.module('app', ['engines']) .factory('car', function($log, dieselEngine) { return { start: function() { $log.info('starting' + dieselEngine.type); } } });angular.module('engines', []) .factory('dieselEngine', function() { return { type: 'diesel' }; });
- 兄弟模块的服务也互相可见
angular.module('app', ['engines', 'cars']);angular.module('cars', []) .factory('car', function($log, dieselEngine) { return { start: function() { $log.info('starting' + dieselEngine.type); } } });angular.module('engines', []) .factory('dieselEngine', function() { return { type: 'diesel' }; });
- 应用中的服务是不能被重名的,父模块的服务会被子模块中的同名模块覆盖。
5. 总结AngularJS 于JQuery
AngularJS内嵌jQuery的一个简化版本jqLite(是一个微小子集,只专注于操纵DOM的例程routine),内嵌jqLite后,AngularJS不再依赖其他外部库。
jQuery与AngularJS虽然可以合作,但是AngularJS围绕模型(由模型的变化来驱动模板(声明式)来更新UI),jQuery围绕DOM,它们是彻底不同的开发范型。
- AngularJS 学习笔记-第一章:速成
- angularjs速成学习个人理解_2表达式
- python一周速成学习笔记
- angularjs速成学习个人理解_1数据与模型绑定
- angularjs速成学习个人理解_4依赖注入
- angularjs速成学习个人理解_5$http服务
- angularjs速成学习个人理解_6$q服务的promise
- angularjs速成学习个人理解_7指令Directives
- angularjs速成学习个人理解_8form中的下拉框
- angularjs速成学习个人理解_9表单验证
- AngularJs-第一章
- AngularJs学习笔记--Forms
- AngularJS入门学习笔记
- AngularJS学习笔记
- AngularJS 学习笔记(邹业盛)
- AngularJs学习笔记--bootstrap
- AngularJs学习笔记--directive
- AngularJs学习笔记--directive
- stm32RS485串口通信——中断接收发送数据
- VS2010中提示无法打开源文件 stdafx.h,.CPP文件中很多类型函数未定义,但是编译通过
- JPA的几个常用方法
- 解决问题的一般思路
- TaintDroid剖析之DVM变量级污点跟踪(下篇)
- AngularJS 学习笔记-第一章:速成
- Dagger2 使用正确姿势。
- Angular系列---- AngularJS入门教程03:AngularJS 模板(转载)
- fork wait
- css基础知识汇总
- InputStream和String的相互转换
- synchronized
- File 类
- 雷霆战机