LOGOAngularJS技术交流基础知识交流LOGO什么是AngularJSAngularJS是协助和搭建单页面工程的开源前端框架,它通过MVC模式使得开发和测试变的更容易AngularJS试图成为WEB应用中的一种端对端的解决方案,它将指导开发整个应用2009年诞生,由MiskoHevery等人创建,后为Google所收购,在google的多个产品中被使用2016年2月AngularJS1.5版本发布2.0版本即将发布是对AngularJS一个重大的变更据说是不往下兼容,也有人说是在开发迁移工具,目前都还不确定,但是唯一确定的一点就是2.0版本将只支持H5的浏览器LOGOAngularJS基础篇提高篇衍生篇LOGO目录基础篇AngularJS的核心思想MVC模块化与依赖注入双向数据绑定指令LOGO目录提高篇过滤器控制器指令(自定义指令)路由及依赖注入服务XHR和服务器通讯事件LOGO目录衍生篇自己动手搭建自动化的前端开发平台扩展主题:用AngularJS开发移动应用TDD与前端自动化测试LOGO问题我们已经学习了类似与Jquery这样的工具了,为什么还有耗费精力学习,angularJS?LOGOJquery与AngularJS比较JqueryAngularJS首先在行为上,他们两个就不一样类库框架声明?命令?用一种命令的方式操作DOM:拿到某一个节点和某一个属性,查看它的值,然后做这做那。采用的是声明的方式DOM操作直接对DOM进行操作很少操作DOM或者压根就不建议操作DOM效率相比于框架来说,确实不具备太多提高效率的地方AG设计上更强调开发效率,比如在框架内它就支持单元测试,再比如降低模块间的耦合度也有利于程序员梳理项目逻辑综上所述:Jquery跟AngularJS两者是出于不同的目的被创建的,解决的也是不同的问题。当一个项目的重点是数据展示和执行,而不是分析,此时可能AngularJS就会更胜一筹LOGOAngularJS核心思想AngularJs的核心思想将视图与业务逻辑解耦。在AngularJS中通过数据视图双向绑定实现。这将提高代码的可测试性。UI视图数据模型视图、数据双向更新这个过程由AngularJs自动进行开发者无需关注LOGOAngularJS核心思想遵循MVC模式开发,鼓励视图、数据、逻辑组件间松耦合。视图控制器服务A服务B服务C服务D通过依赖注入解耦通过数据、视图双向绑定解耦LOGOMVCLOGO为什么需要MVC?代码规模越来越大,切分职责是大势所趋为了复用:很多逻辑是一模一样的为了后期维护方便:修改一块功能不影响其它功能LOGO数据模型视图1视图2控制器Controller的实现方式1LOGO数据模型视图1视图2控制器1问题:如果“控制器1”和“控制器2”里面有2个方法是一模一样的,怎么办?控制器2Controller的实现方式2LOGO数据模型视图1视图2控制器1在ng中请不要这样做!控制器2通用控制器继承继承Controller的实现方式3LOGO数据模型视图1视图2控制器1控制器2ServiceAngularJS中的Controller实现LOGO不要试图去复用Controller,一个控制器一般只负责一小块视图不要在Controller中操作DOM,这不是控制器的职责不要在Controller里面做数据格式化,ng有很好用的表单控件不要在Controller里面做数据过滤操作,ng有$filter服务一般来说,Controller是不会互相调用的,控制器之间的交互会通过事件进行ng使用Controller的最佳实践LOGO$scope是一个POJO(PlainOldJavaScriptObject)$scope提供了一些工具方法$watch()/$apply()$scope是表达式的执行环境(或者叫作用域)$scope是一个树型结构,与DOM标签平行子$scope对象会继承父$scope上的属性和方法每一个Angular应用只有一个根$scope对象(一般位于ng-app上)$scope可以传播事件,类似DOM事件,可以向上也可以向下$scope不仅是MVC的基础,也是后面实现双向数据绑定的基础可以用angular.element($0).scope()进行调试AngularJS中MVC的核心是$scopeLOGO作用域作用域的生命周期创建链接更新销毁创建控制器或者指令的时候,会创建新的作用域,在在这个新建的控制器函数运行时将作用域传递进去在Angular开始运行的时候,所有的$scope对象都会附加或者链接到视图中当事件循环运行时,它通常执行在顶层$scope对象上,每个子作用域都执行自己的脏值检测。每个监控函数都会检查变化。如果检测到任意变化,$scope对象就会触发指定的回调函数。清理作用域Angular会来进行,当然我们也可以自己手动进行清理调用$scope上的destory方法即可LOGO模块化与依赖注入LOGO一切都是从模块开始的LOGOng官方推荐的模块切分方式appcontrollersdirectivesservicesroutesfilters任何一个ng应用都是由控制器、指令、服务、路由、过滤器等有限的模块类型构成的控制器、指令、服务、路由、过滤器分别放在一个模块里面用一个总的app模块作为入口点,它依赖其它所有模块LOGO模块的写法模块的简单写法:angular.module('modulename',[x1,x2])//依赖于x1、x2模块.directive('directiveName',function(){}).factory('a',function(){return123;})//创建服务.filter('b',function(){})//创建过滤器.value('d',123)//创建变量,创建后可修改.contract('c',324)//创建常量创建后不可修改LOGO配置块、运行块模块的两个部分:配置块、运行块angular.module('modulename',[x1,x2]).config(function($provide,$compileProvider,$filterProvider){$provide.value('a',123)$provide.factory('a',function(){return123;})$compileProvider.directive('directiveName',...).$filterProvider.register('filterName',...);});•配置块:在实例工厂(provider)注册和配置阶段运行。只有工厂、常量才可以注入到配置块中(常量的配置要放在前面)。•运行块:注入器(injector)被创建后执行,被用来启动应用。实例和常量、变量等都能被注入。angular.module('modulename',[x1,x2]).run(function($timeout){//运行的代码});LOGOAngular的依赖注入实现每一个Angular应用都有一个injectorinjector负责自动处理依赖关系、实例化对象对用户代码来说,injector是透明的injector会自动分析函数签名,注入所需要的对象声明依赖关系的三种方式:DI可以用在各种不同的地方,主要用在controller和factory中LOGO依赖注入的核心原理分析匹配参数名fn.$injections=[]使用fn.call或者apply传递需要注入的对象双向数据绑定LOGO最简单的例子LOGOAngularJs双向绑定的大概步骤用$watch()监控数据模型$digest()启动脏值检测触发视图变化编译指令,设置监听器定时器轮询、对象“深比较”用事件通知指令刷新视图LOGOAngularJs双向绑定的详细解释在编译时,Angular使用$watch()在对应的$scope上添加了监控,一旦$scope中的属性值发生变化,这里就会跟着变。(脏值检测的$digest过程)在指令编译时,Angular对input添加了事件监控,会自动把input的值设置到$scope中的对应属性上。LOGOAngularJs双向绑定的核心代码LOGO关于双向数据绑定的一些忠告监控的表达式不要过于复杂,表达式数量不要太多监听函数内不要有DOM操作,那样会显著降低性能不能互相监听对方会修改的属性,以免形成交叉引用ng默认的TTL是10次深拷贝式的脏值检测会消耗更多内存(树形的JSON数据尤其如此)LOGO指令指令LOGO指令什么是指令指令是AngularJS用来扩展浏览器能力的技术之一。在DOM编译期间,和HTML关联着的指令会被检测到,并且被执行。这使得指令可以为DOM指定行为,或者改变DOM的结构。LOGO指令指令如何被检测第一步:编译DOM第二步:链接指令从ng-app开始,获取DOM节点,使用$compile方法遍历DOM节点收集指令,将这些指令放入一个队列中。然后逐个调用这些指令的$compile方法,逐个返回链接函数。这些函数会被集合在一个方法对象里。最后$compile方法会返回这个方法对象。调用第一步$compile返回的方法,将作用域(scope,即数据对象)与模板链接起来。在这些链接函数里,会对DOM模板添加监听事件,同时建立对作用域(scope)的监听,实现双向绑定。将这两部分分开是为了提高效率,以应对ng-repeat等需要重复产生节点的情况,避免重复编译。生成链接函数集合LOGO指令的命名规则关于自定义指令的命名,你可以随便怎么起名字都行,官方是推荐用[命名空间-指令名称]这样的方式,像ng-controller。不过千万不要用ng-前缀了,防止与系统自带的指令重名。另外一个需知道的地方,指令命名时用驼峰规则,使用时用-分割各单词。如:定义myDirective,使用时像这样:my-directive。LOGO声明指令的方式声明指令并不是一定要创建元素,也可以创建属性、类、注释格式如下:my-directive/my-directivedivmy-directive/divdivclass=“my-directive”/div!--directive:my-directive--创建类似的指令的时候只要在自定义指令里面指定restrict就可以,元素(E),属性(A)、类(C)、注释(M),也可以一次指定多个例“ACEM”LOGO内置指令所有已ng前缀开头作为命名空间的指令都是AngularJS提供的内置指令基础的ng属性指令ng-href;ng-src;ng-disabled;ng-checked;ng-readonly;ng-selected;ng-class;ng-styleLOGO布尔属性1、ng-disabled:可以绑定的html元素input(text,checkbox,radio,number,url,Email,submit);textarea;select;buttonHtml中的disabled属性只会禁用这个输入字段,通过ng-disabled可以根据值来具体的判断,参考例子directive5-disabled.html2、ng-readonly,ng-checked,ng-selected的使用方式跟disabled差不多这里就不多做举例了LOGO类布尔属性ng-href参考例子:directtive7-href.htmlng-href跟ng-src都能够有效的帮助重构和避免错误,因此在改