11/2/2016, 4:33:40 PM
随着浏览器性能提升,更多Web Page演变为Web App,特别是在中大型的项目中,就需要一个 前端框架 来:
眼下潮流的框架太过于现代,入门门槛过高,学习React,Vue 2,Angular 2,需要首先学习npm、webpack、jsx、ES6、甚至Typescript。而且变化非常快,一些需要写前端的后端人员可能力不从心😂
而学习AngularJS 1 只需要基础的前端知识即可,Angular 1 属于经典的MVC类框架,API已经非常稳定,社区成熟,对低版本浏览器支持好(1.2以前版本支持IE6),性能依然满足大部分场景。
jQuery是库,面向DOM,Angular 面向模型,思路要转变。
同样的一个简单需求,可以明显看得出jQuery中业务代码,直接操作DOM代码揉杂在一块,而Angular中JS代码关心业务逻辑,HTML描述界面非常的清晰。
一般而言,使用jQuery的弊病在于,
$()
的使用方式很容易造成性能问题 。当然框架本身的学习成本,是对项目后期的投资,不过项目本身不复杂,完全没必要使用前端框架,用了反而适得其反。
AngualrJs则通过数据双向绑定屏蔽了DOM操作,MVC解耦代码,依赖注入,自定义指令来复用代码,然后配合强大的路由,本地化,安全特性等,成功地成为了前ES6时代最流行的前端框架。
作用域(scope)是AngualrJs中的基础概念,一般而言,一个controller一个scope , 每个controller中内置一个数据模型对象$scope
。而 $scope
对象是定义应用业务逻辑、控制器方法和视图属性的地方 。
上面的Demo中,业务变量number
是$scope
的一个属性,然后通过数据绑定的方式链接到view。
<div>{{number}}</div> <input type="number" ng-model="number">
{{ }}
语法绑定到view中,这个符号还可以修改。
angular.module('app',[],function($interpolateProvider) { $interpolateProvider.startSymbol('(%'); $interpolateProvider.endSymbol('%)'); })
而 ng-model
就是 AngularJS 1中的一大特色: 数据双向绑定 ,model中数据变化了view中就会自动改变,而相应的view中(表单)变化了,也会自动同步到model。
Angular 1.3 之后支持了 controller as
的语法,上面Demo就可以这样写了
<div ng-app="app" ng-controller="MainCtl as vm"> <div> {{vm.number}} </div> <input type="number" ng-model="vm.number" require> <button ng-click="vm.addOne()"> +1 </button> </div>
angular.module('app', []) .controller('MainCtl', function() { this.number = 0; this.addOne = function() { this.number += 1; } })
这样controller中不在显示的依赖$scope
,完全就是普通的函数,干净,好测试,并且也有利于避规一些scope的原型继承导致的双向同步的bug,推荐这样书写。
需要注意的是controller中只操作数据即可,不要试图操作DOM,这点jQuery的同学一定要忍住😄,如果需要操作DOM,请使用指令,后续会讲到。
简单说一下模块
//声明模块 angular.module(‘app’, []);
相对独立的功能块可以声明为一个模块,然后通过依赖注入相互引用,这样达到方便的复用,控制,一般第三方插件都是通过模块方式引入到你的应用代码,而自身的业务代码也可以根据实际情况切分不同的模块。
到这一步已经可以开始写一定的Angualr应用了,按照一定功能粒度划分模块,然后纯粹js业务代码,之后数据绑定到view。
实际上之后Angular 1的种种概念都是围绕上述的展开和补充。
AngualrJS 1中数据模型对象 $scope
,就是普通的javascript对象(POJO),你在上面任意的添加属性和方法,Angular都支持并且能够实时双向绑定的“黑魔法”就是脏检查。
脏检查字面理解就是循环对比前后值,如果不相同说明就是“脏”的然后执行相应的操作,直到所有值相同,或者超出循环次数范围
如果说scope是入门的核心,那么Angualr脏检查就是入门到精通的核心。
上面Demo timeout的例子中,通过原生setTimeout方法修改的变量,并没有更新到视图上,而1000毫秒setTimeout的能够更新。说明:
$timeout
, $http
都是为了能够出发脏检查的 $digest
,所以尽量使用AngularJS提供的方法。$$watchers
。1000毫秒setTimeout的能够更新是因为,这个时间点,恰好由$timeout
方法触发了一次检查。因此这也就导致了从另一个角度分析脏检查。上面例子说明了AngularJS脏检查的特性,手动触发,全局检查。
每次循环都要全部遍历一边$$watchers
的值,而且如果被检测的值相互有依赖,还要循环多次。因此AngularJS脏检查很容易导致性能问题。因此
{{::number}}
语法有助于减少监控数量,因为 ::
开头的表达式都被认为是一次性表达式。一次性表达式一经赋值就会移除监控。directive
directive
,以及用指令写组件指令是Angular中相对低层,却又非常强大的功能。如果一般使用并不需要了解,使用内置的指令已经可以完成绝大多数功能。
AngularJs中本身以及内置了大量的指令,例如, ng-if
, ng-repeat
, 甚至ng-controller
。
也可以通过下面方式来自定义指令。
angular.module('myApp', []) .directive('myDirective', function() { return { restrict: String, priority: Number, terminal: Boolean, template: String or Template Function: function(tElement, tAttrs) (...}, templateUrl: String, replace: Boolean or String, scope: Boolean or Object, transclude: Boolean, controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }, controllerAs: String, require: String, link: function(scope, iElement, iAttrs) { ... }, compile: // 返回一个对象或连接函数,如下所示: function(tElement, tAttrs, transclude) { return { pre: function(scope, iElement, iAttrs, controller) { ... }, post: function(scope, iElement, iAttrs, controller) { ... } } // 或者 return function postLink(...) { ... } } }; });
自定义指令相对复杂难懂,算是AngularJS中高阶能够,可以从下面三点简单理解的是:
来自官网 AngularJS的Tab例子可以很好的说明controller的使用。
上述Nestlist Demo中使用指令的渲染速度明显快过使用Angular模版方式。
原因在于DOM写入是种相当耗时操作,大批量数据最好拼好HTML字符串一次性 innerHTML
到页面中,这样的速度远快于逐步展开插入(Angualr 模版渲染方式)的速度 ,这也是AngualrJs中指令在现在看来也是很强大有用的功能。
=
强大的双向绑定,而且AngularJs 1.5 scope中 <
带了目前流行类似单向绑定的功能。再次多说一点的是,指令中能够精准定义scope交互的功能,从脏检查的角度来说也能在很大程度上减少$$watchers
的数量,以此来增强性能。
Promise的相关可以通过这篇文章来看,译用漫画来解说AngularJs中的Promises 。
AngularJS 1其实还有蛮多概念,不过毕竟是有点过时的框架,上述所写便是Angular 1值得关注留意的知识点了,应该能够足够了解Angular 1。