AngularJS的思考
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的思考的更多相关文章
- AngularJS 动画总结
对读过的几篇文章的总结,尽量保证逻辑性,不断补充.精简.更正. 后面会列出参考文章地址,方便以后取用.感谢各位作者以及翻译者. AngularJS 动画思考 一.如何使用 1)我们需要构建什么 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 ...
- 具有jQuery背景的程序员如何转换为AngularJS思考模式(译)
最近一直在研究angularjs,最大的感受就是它和之前的jQuery以及基于jQuery的各种库设计理念完全不同,如果不能认识到这点而对于之前做jQuery开发的程序员,去直接学习angularjs ...
- 对于angularJS的一点思考
已经找好工作近两周了,入职基本上还算顺利,自己两年来的挑灯夜战也算是有了收获,于是这两周基本上是按部就班的工作,没有学习什么新技术.在上个公司的时候,同事在项目中使用angularJs,之前他也没有接 ...
- angularjs实现 checkbox全选、反选的思考
之前做了一周的打酱油测试,其实感觉其实测试也是上辈子折翼的天使. 好长时间没写代码,感觉好多都不会了. 感谢这周没有单休,我能看熬夜看奥运了.我能有时间出去看个电影,我能有时间出去逛个商城,我能有时间 ...
- angularJs 使用中遇到的问题小结【二:购物车引起的问题思考】
问题描述 :购物车引起的问题思考 业务逻辑是这样的:我商品加入购物车后,——>点击购物车图标——>进入订单列表(这里的数据只有首次会加载服务器数据,后面就不会执行控制器的方法了,这里的跳转 ...
- 关于AngularJS与其他前端框架混合使用的思考
AngularJS 是一个为动态WEB应用设计的结构框架,拥有双向数据绑定,模板,MVVM,依赖注入,指令5大优点,Angular最有诱惑力的就是数据绑定功能,使用MVC模式进行开发,Angular在 ...
- AngularJS track by $index引起的思考
今天写了一段程序,只是一个简答的table数据绑定,但是绑定select的数据之后,发现ng-change事件失去了效果,不知道什么原因. 主要用到的代码如下: <div id="ri ...
- MVVM大比拼之AngularJS源码精析
MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...
随机推荐
- SQL语句的添加、删除、修改多种方法 —— 基本操作
添加.删除.修改使用db.Execute(Sql)命令执行操作 ╔----------------╗ ☆ 数据记录筛选 ☆ ╚----------------╝ 注意:单双引号的用法可能有误(没有测试 ...
- 160815、mysql主从复制/读写分离
mysql主从复制主服务器IP:192.168.99.10从服务器IP:192.168.99.20(一)安装mysql(主从服务器操作相同)yum -y install gcc gcc-c++ ncu ...
- 七、H5 直播视频播放
HTML5实现视频直播功能思路详解_html5教程技巧_脚本之家 https://m.jb51.net/html5/587215.html 七.H5 直播视频播放 移动端iOS和 Android 都天 ...
- linux系统各种日志存储路径和详细介绍
Linux常见的日志文件详述如下1./var/log/boot.log(自检过程)2./var/log/cron (crontab守护进程crond所派生的子进程的动作)3./var/log/mail ...
- jQuery EasyUI 简介
简介 jQuery EasyUI 是一个基于 jQuery 的框架,集成了各种用户界面插件. 特点: ①easyui 是一个基于 jQuery 的框架,集成了各种用户界面插件. ②easyui 提供建 ...
- MySQL优化方案二
摘自:http://www.thinkphp.cn/topic/3855.html 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需 ...
- python小知识点复习
join 与 split 对应,join传入的列表只包含字符串卡类型 字典 dic = {'x':1, 'y':2, 'x':3} print(dic) # {'x': 3, 'y': 2} 重复的k ...
- Python高级教程-返回函数
函数作为返回值 高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回. 要实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = 0 ...
- JS连等赋值的坑
cnblogs标题: JS连等赋值的坑 关于JS连等赋值有个经典的笔试题: var a = {n: 1}; var b = a; a.x = a = {n: 2}; console.log(a.x); ...
- web前端编码规范
简要介绍 本文通过参考百度腾讯等前端编码规范(链接建文末),得出个人习惯的编码规范.个人编码规范采用在不影响可读性的情况下能省就省,尽量简洁,不需要就直接去掉. 最佳原则不管是个人编码规范还是团队编码 ...