Hipo log

AngularJS 1 教程

Last updated on

toc

Intro

为什么需要前端框架

随着浏览器性能提升,更多Web Page演变为Web App,特别是在中大型的项目中,就需要一个 前端框架 来:

为什么2016年的今天仍然可以学习Angular 1

眼下潮流的框架太过于现代,入门门槛过高,学习React,Vue 2,Angular 2,需要首先学习npm、webpack、jsx、ES6、甚至Typescript。而且变化非常快,一些需要写前端的后端人员可能力不从心😂

而学习AngularJS 1 只需要基础的前端知识即可,Angular 1 属于经典的MVC类框架,API已经非常稳定,社区成熟,对低版本浏览器支持好(1.2以前版本支持IE6),性能依然满足大部分场景。

和jQuery 的不同

jQuery是库,面向DOM,Angular 面向模型,思路要转变。


JS Bin on jsbin.com

同样的一个简单需求,可以明显看得出jQuery中业务代码,直接操作DOM代码揉杂在一块,而Angular中JS代码关心业务逻辑,HTML描述界面非常的清晰。

一般而言,使用jQuery的弊病在于,

当然框架本身的学习成本,是对项目后期的投资,不过项目本身不复杂,完全没必要使用前端框架,用了反而适得其反。

学习AngularJS 1

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的种种概念都是围绕上述的展开和补充。

Angualr 1实现双向绑定的脏检查

AngualrJS 1中数据模型对象 $scope,就是普通的javascript对象(POJO),你在上面任意的添加属性和方法,Angular都支持并且能够实时双向绑定的“黑魔法”就是脏检查。

脏检查字面理解就是循环对比前后值,如果不相同说明就是“脏”的然后执行相应的操作,直到所有值相同,或者超出循环次数范围

如果说scope是入门的核心,那么Angualr脏检查就是入门到精通的核心。

从使用角度来说脏检查


JS Bin on jsbin.com

上面Demo timeout的例子中,通过原生setTimeout方法修改的变量,并没有更新到视图上,而1000毫秒setTimeout的能够更新。说明:

从性能角度来说脏检查

上面例子说明了AngularJS脏检查的特性,手动触发,全局检查。

每次循环都要全部遍历一边$$watchers的值,而且如果被检测的值相互有依赖,还要循环多次。因此AngularJS脏检查很容易导致性能问题。因此

指令 directive,以及用指令写组件

指令是Angular中相对低层,却又非常强大的功能。如果一般使用并不需要了解,使用内置的指令已经可以完成绝大多数功能。

AngularJs中本身以及内置了大量的指令,例如, ng-ifng-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中高阶能够,可以从下面三点简单理解的是:

JS Bin on jsbin.com

来自官网 AngularJS的Tab例子可以很好的说明controller的使用。


JS Bin on jsbin.com

上述Nestlist Demo中使用指令的渲染速度明显快过使用Angular模版方式。

原因在于DOM写入是种相当耗时操作,大批量数据最好拼好HTML字符串一次性 innerHTML到页面中,这样的速度远快于逐步展开插入(Angualr 模版渲染方式)的速度 ,这也是AngualrJs中指令在现在看来也是很强大有用的功能。

再次多说一点的是,指令中能够精准定义scope交互的功能,从脏检查的角度来说也能在很大程度上减少$$watchers的数量,以此来增强性能。

Promise

Promise的相关可以通过这篇文章来看,译用漫画来解说AngularJs中的Promises


AngularJS 1其实还有蛮多概念,不过毕竟是有点过时的框架,上述所写便是Angular 1值得关注留意的知识点了,应该能够足够了解Angular 1。