AngularJS实践

什么是AngularJS

AngularJS的核心理念是什么? 在我看来,Angualr的核心思想是:Template + Scope => HTML, Template就是各种可以复用的模板,Scope就是数据.

WEB前端原本是DOM构成一个树形结构,然后数据杂乱分布. 开发者用JQuery之类的工具在DOM上添加各种各样的数据(data, trigger, listener)等.当网页的结构复杂起来之后,各种数据之间的关联错综复杂,到最后几乎没有人可以说清楚这个庞然大物里存在多少关联. 复杂的WEB应用里有大量同类型的节点,也导致JQuery里的$("#id")到处存在,维护性极差.

AngularJS从另外一个角度来解决,将数据组织成树状结构,每一个数据节点绑定对应的模板之后就渲染出对应的HTML. 所有的数据,包括函数,触发器都绑定在这棵树上, 每一个节点的渲染过程只跟该节点上的数据以及绑定的模板有关,需要协调的关系只能通过这棵树向上追溯. 比如两个模块需要共享一个用户登录状态时,可以将用户状态定义在两个元素上节点的共同祖先节点上,这样生成两个元素节点时都引用祖先的数据,就可以生成统一的HTML了.

这是从上往下生成HTML的过程,那么如果祖先节点上的状态发生了变化,怎么让子孙节点也同步变化呢. AngularJS提供了一个检查机制, 模板是不会变化的,而HTML的生成只与模板和数据相关. 因此AngularJS沿着数据树根节点往下检查,一旦某个数据节点发生了变化,就立刻重新渲染这个节点.

为了能及时进行检查, AngularJS绑定了WEB页面上的大部分操作, 比如按键等. 一旦有这些操作发生时, AngularJS都会开始脏检查, 这样可以确保页面的不断更新. 当然这一切是建立在现在浏览器处理能力越来越强的基础上的.

AngularJS与JQuery

AngularJS也需要操作DOM,因此AngularJS有一个JQuery的子集JQLite来做DOM操作. 但AngularJS的理念是模块化和封闭化, 每一个节点的渲染封闭在该节点的DATA和Template内部, 只能通过父节点了解外部变化. 这个与JQuery那种完全扁平的结构是冲突的, 使用JQuery,我们可以在随意的位置修改HTML上任意一个节点. 这种方便性就是导致最后页面无法维护的原因.

正因为这个理念的原因, AngularJS和JQuery其实是最好不要共存的. 在使用AngularJS的很多时候我们都会有忍不住拿出JQuery来的冲动, 明明看起来很容易完成的任务, 被AngularJS封装起来后仿佛变得复杂了很多. 这个时候更建议大家重新看一下自己的设计是否需要调整. AngularJS是一个全局的理念, 不是可以一半JQuery一半AngularJS (当然有些大神能够很好的将项目划分开, 也就尽信书不如无书了, 这个当然没有绝对的方案).

Directive的compile, link

Angular中controller是用来将view上的操作与实际业务逻辑挂钩,如果需要对dom进行操作时,directive才是合适的选择。directive中有两个非常重要的概念:compile和link

  • compile

    compile是一个预处理过程,directive在compile是与实际状态无关的,compile的目的就是为了得到最终的link函数。
  • link

    link函数负责在得到具体的scope之后渲染出最终的HTML页面。

常见问题

一些技巧

Server端初始化页面参数

我们经常会遇到的问题是需要从Server得到整个页面的一些初始化条件,然后再用AngularJS在页面端运行整个App。 有一个解决方案是在页面端通过Ajax去Server请求。不过既然整个页面都是从Server请求来的,这个Ajax请求未免有点多余。

这里提供一个解决方案,利用页面渲染过程在页面上写入启动参数。

我的实际做法如下:

在页面模板上写一个angular service:(我这里用的是Jade渲染引擎,读者只关注里面的js code就好)

    script.
var serverInit = angular.module("serverInit", []);
serverInit.factory("serverParams", function(){
var params = !{JSON.stringify(serverParams)};
return params;
});

然后在server端渲染时给出参数:

	res.render('page', {serverParams : {
Id : "51955"
}});

这样在页面端我就可以使用这个初始化参数了

    var app = angular.module("testApp", ['serverInit']);
app.controller("testController", function(serverParams){
var id = serverParams.Id;
}

Angular Mocks测试时不拦截Http请求

在测试Angular程序时,我们经常会使用到AngularMocks库,这个库会用$httpBackend拦截被测试代码中的$http请求,这样可以测试代码是否如预期发送出了http请求,并且返回伪造的结果。

但如果我们不需要请求被拦截,而是需要请求发送到真实Server怎么办?StackOverflow上有一个网友给出了一个精彩的方案:

首先在测试代码文件中写一个新的angular module。

	angular.module('httpReal', ['ng'])
.config(['$provide', function($provide) {
$provide.decorator('$httpBackend', function() {
return angular.injector(['ng']).get('$httpBackend');
});
}])
.service('httpReal', ['$rootScope', function($rootScope) {
this.submit = function() {
$rootScope.$digest();
};
}]);

然后在需要测试代码中注入httpReal Service, 这个Service会将真正的$httpBackend替换回来!这样angularMocks的拦截功能就无效了。

	describe('my service', function() {
var myService, httpReal; beforeEach(module('myModule', 'httpReal')); beforeEach(inject(function( _myService_, _httpReal_ ) {
myService = _myService_;
httpReal = _httpReal_;
})); it('should return valid data', function(done) {
myService.remoteCall().then(
function(data) {
expect(data).toBeDefined();
done();
}, function(error) {
expect(false).toBeTruthy();
done();
}); httpReal.submit();
});
});

注意这个submit(),因为在AngularJS中,使用了$q来返回promise,而promise的触发是需要在$scope做脏检查的时候做的,而在UnitTest需要手动调用一次$digest去触发。

AngularJS的思考的更多相关文章

  1. AngularJS 动画总结

    对读过的几篇文章的总结,尽量保证逻辑性,不断补充.精简.更正. 后面会列出参考文章地址,方便以后取用.感谢各位作者以及翻译者. AngularJS 动画思考 一.如何使用 1)我们需要构建什么 2)如 ...

  2. 用angular来思考问题How do I “think in AngularJS” if I have a jQuery background?

    [翻译]How do I “think in AngularJS” if I have a jQuery background? 1. 不要先设计页面,然后再使用DOM操作来改变它的展现 在jQuer ...

  3. 具有jQuery背景的程序员如何转换为AngularJS思考模式(译)

    最近一直在研究angularjs,最大的感受就是它和之前的jQuery以及基于jQuery的各种库设计理念完全不同,如果不能认识到这点而对于之前做jQuery开发的程序员,去直接学习angularjs ...

  4. 对于angularJS的一点思考

    已经找好工作近两周了,入职基本上还算顺利,自己两年来的挑灯夜战也算是有了收获,于是这两周基本上是按部就班的工作,没有学习什么新技术.在上个公司的时候,同事在项目中使用angularJs,之前他也没有接 ...

  5. angularjs实现 checkbox全选、反选的思考

    之前做了一周的打酱油测试,其实感觉其实测试也是上辈子折翼的天使. 好长时间没写代码,感觉好多都不会了. 感谢这周没有单休,我能看熬夜看奥运了.我能有时间出去看个电影,我能有时间出去逛个商城,我能有时间 ...

  6. angularJs 使用中遇到的问题小结【二:购物车引起的问题思考】

    问题描述 :购物车引起的问题思考 业务逻辑是这样的:我商品加入购物车后,——>点击购物车图标——>进入订单列表(这里的数据只有首次会加载服务器数据,后面就不会执行控制器的方法了,这里的跳转 ...

  7. 关于AngularJS与其他前端框架混合使用的思考

    AngularJS 是一个为动态WEB应用设计的结构框架,拥有双向数据绑定,模板,MVVM,依赖注入,指令5大优点,Angular最有诱惑力的就是数据绑定功能,使用MVC模式进行开发,Angular在 ...

  8. AngularJS track by $index引起的思考

    今天写了一段程序,只是一个简答的table数据绑定,但是绑定select的数据之后,发现ng-change事件失去了效果,不知道什么原因. 主要用到的代码如下: <div id="ri ...

  9. MVVM大比拼之AngularJS源码精析

    MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...

随机推荐

  1. HDU 5892 Resident Evil

    题目链接:传送门 题目大意:有50种动物,给你n*n的矩阵,m次操作,P代表加入操作,在左上角 x1,y1 到右下角 x2,y2,的矩形范围内加入 种类为x,数量为y的动物. Q代表询问操作,在左上角 ...

  2. float元素一定要闭合

    float:left; float:right; 一定要两个元素一起放float

  3. Office word中去掉首页的页眉

    1.首先将光标位置移动到第二页的开始,然后点击页面布局命令. 2.页面布局里面找到分隔符,找到下一页的分隔符.(分页符分页) 3.双击第二页的页眉,打开页眉编辑菜单.将连接到前一条页眉的命令去掉. 4 ...

  4. java反射——方法

    大家都知道反射技术在Java里面时非常重要的一个技术点,因为Java好多框架的编写都是基于反射的,别的不多说,spring框架里面的IOC就是基于反射实现.那么什么是反射呢?JAVA反射机制是在运行状 ...

  5. Linux网络配置:设置IP地址、网关DNS、主机名

    查看网络信息 1.ifconfig eth0 2.ifconfig -a 3.ip add 设置主机名需改配置文件: /etc/hosts /etc/sysconfig/network vim /et ...

  6. Centos7 下谷歌日志库GLog配置

    1 glog下载地址 https://code.google.com/archive/p/google-glog/downloads glog-0.3.3.tar.gz 需要FQ,直接打不开 2 解压 ...

  7. XML 之快速入门

    XML 简介 - XML, 即可扩展标记语言(eXtensible Markup Language), 是一种标记语言. - 标记型语言: 使用标签进行操作 - 可扩展: XML 的标签可以自定义 - ...

  8. (4.8)SET ANSI_NULLS ON、SET QUOTED_IDENTIFIER ON

    T-SQL支持在与空值进行比较时,允许比较运算符返回 TRUE 或 FALSE. 通过设置 ANSI_NULLS OFF 可将此选项激活.当 ANSI_NULLS 为 OFF 时,如果 ColumnA ...

  9. 解决127.0.0.1 localhost 劫持问题

    在一个安装iis的过程中,把网站部署上去之后就发现127.0.0.1或者localhost都会跳转到一个莫名的网站,发现断网之后就是会跳转到一个Http://www.76636.com 类似这种的网站 ...

  10. Hbase 学习笔记5----hbase region, store, storefile和列簇的关系

    The HRegionServer opens the region and creates a corresponding HRegion object. When the HRegion is o ...