再来看看关于Angularjs其它一些我觉得挺重要的特性
1.依赖注入
这个是老概念了,Angularjs通过参数的形式把实例传递到调用的模块中去,例如下图
灰色的Service 实例就作为一个参数传递到业务逻辑Controller中去的,从而分层,这种方式在Flex Parsley中也是非常常见的,只不过Flex中常用是先用config文件来定义注入关系。
Angularjs中又n种注入声明的方法,controller filter directive factory config run。前三个分别用于Angularjs自己特有的3种类型的声明,factory多用于service啊,其它工具类的声明,config和run这2个没多做研究看文档应该是执行时间的不同。(run我在项目里从没遇到过,具体没研究过不能瞎说,等博主以后深入了解了再来补充)
2.Directive
官方对于Directive的解释如下,
What are Directives?
At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler (
$compile
) to attach a specified behavior to that DOM element or even transform the DOM element and its children.Angular comes with a set of these directives built-in, like
ngBind
,ngModel
, andngClass
. Much like you create controllers and services, you can create your own directives for Angular to use. When Angularbootstraps your application, the HTML compiler traverses the DOM matching directives against the DOM elements.
我认为Directive在实际开发中有2个作用:
(1):类似Flex的自定义组件,比如你需要在项目中引入JQuery的tree组件jstree,那么你可以定义一个名为ng-tree的Directive在某个div上,当Angularjs解析到ng-tree这个标签的时候他就会往这个div里生成你定义好的jstree并且重新生成这部分的html。
var directives = angular.module('documentDesigner.directives', []); directives.directive('treeView', function(){ return { restrict: 'C', scope: { isolatedTreedata:"@treeData"}, link: function(scope,element,attrs){ attrs.$observe('treeData', function(value) { var dataSet = JSON.parse(value); var tree = element.jstree({ 'core' : { 'data' : dataSet }, "checkbox" : { "keep_selected_style" : false, "three_state":false }, 'plugins' : ['unique','wholerow'] }); tree.bind("select_node.jstree", function (e, data) { //todo }); tree.bind("hover_node.jstree",function(e,node){ //todo }); }); } }; });
(2) 可以用Directive定义一些通用的组件行为或者属性,比如自带的ng-disabled(设置组件的disabled的状态),比如你也可以自定义ng-popup的Directive,一旦使用了这个标签的组件都可被触发弹出,等等。
Directive可谓相当灵活的一个功能,是Angularjs能被用于实际项目的重中之重。因为完全单纯的model绑定ui,通过修改model在更新ui的想法在实际开发过程中是靠谱的,在一些细枝末节的地方我们还是要使用直接读取对象修改属性的方式jquery api来灵活方便的操作dom对象,所以我们尽可能得把这些直接的dom操作封装在Directive中。
3.异步请求
Angularjs提供了2种方式,一种是factory创建一个service类,引用内置的$http对象进行get,post等restful的请求,另外一种是使用$resources对象来封装一组restful请求。个人感觉还是用$http在回调的异常处理方面更加灵活,$resources更加便捷适用于快速demo的开发。
举个栗子
$http方式
services.factory('Reports',['$http',function($http){
return{
save:function(reportModel){
$http.post('/someUrl', {model:reportModel}). success(function(data, status, headers, config) { // this callback will be called asynchronously // when the response is available }). error(function(data, status, headers, config) { // called asynchronously if an error occurs // or server returns response with an error status. });
}
}
}]);
$resource方式
services.factory('Reports',['$resource','localErrorInterceptor',function($resource,localErrorInterceptor){ return $resource(context+'/podtree/:reportId',{reportId:'@reportId'}, { get:{method:'GET',interceptor: localErrorInterceptor}, query:{method:'GET',interceptor: localErrorInterceptor,params:{reportId:''},isArray:true} }); }]);
你只要定义restful url的pattern,增删改查的各类方法他都会帮你自动实现(你甚至不用自己去声明post,delete,get等方法),你只要直接调用Reports.$save(),Reports.remove(),Reports.get(id),Reports.query()等内置函数就能实现调用,比较方便可以少写不少代码。
4.单元测试
之前做Flex测试一直没有形成一套好的测试机制,单元测试其实最多充其量也测试写Controller层的一些方法,如果遇到和后台交换的操作还更加麻烦。
Angularjs 提供了Karma和Jasmine的Unit Test的方式,我只在demo中用到过单元测试,具体项目中感觉前台应用单元测试意义不大,比较靠谱的是模拟用户行为的录像式测试会更加靠谱一些,Angularjs也提供了名为e2e的测试方式,类似写用户动作执行脚本的测试(这个感觉实际意义更大,不过需要程序员花费更多的时间去写脚本来模拟各种case),由于博主在实际开发中没有亲自体验过e2e的测试,所以这里就不展开了待下个项目实践后再来补充,对e2e感兴趣的可以戳
未完待续...