DataBinding Providers Validators Directives
Controllers Modules Expressions Factories
Services Filters Dependency Injection Scope
AngularJS优缺点比较
优点
MVVM 数据和视图绑定,省去频繁操作jquery更新dom,自带了丰富的Angular指令,整体功能比较完善,
包含模板,数据双向绑定,路由,模块化,服务,过滤器,依赖注入等所有功能
自定义Directive组件,组件化,模块化
引入后台开发的一些概念,MVC,服务,依赖注入 ,容易构建SPA单页面应用
文档丰富,生态圈相对较好,问题容易解决
缺点
相比jquery,代码侵入性过大,依赖太多而且剥离升级困难,另外与jquery组件冲突严重,需要$apply()
directive一些指令生命周期定义复杂,容易如门但学习曲线陡峭
本身有些自带指令ng-route不好用,要依赖第三方,ui router仍旧问题太多,复杂路由很难用
版本迭代变化太大,2.0完全颠覆以前东西,甚至都不能说是同一个框架,1.x设计有问题(同第一条)
MVVM
Module
<script src="../../../resources/plugin/angular/angular.min.js"></script>
var studyApp = angular.module("studyApp", ["pascalprecht.translate", "kendo.directives", "wl.directives", "wl.controls", "study.controls", 'ui.router', "oc.lazyLoad"]);
studyApp.controller("frameController", function ($http, $scope, $timeout, $state, $translate, $filter, $rootScope) {
//省略........
});
AngularJS允许我们使用angular.module()方法来声明模块,
这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖的模块列表,也就是可以被注入到模块中的对象列表。
angular.module('myApp', []); 用来定义模块,相当于AngularJS模块的setter方法。
调用这个方法时如果只传递一个参数,就可以用它来引用模块。
angular.module('myApp') ; 用来获取对myApp模块的引用,相当于AngularJS模块的getter方法,。
var planApp = angular.module("planApp");
planApp.controller("strContentCtrl", function($rootScope,$http,$scope,$timeout,$state,$stateParams,$transitions,$filter){
//省略......
});
Module的使用
(Recommended Setup)推荐设置
大规模的应用,建议将自己的应用按照如下建议,拆分为多个module:
service module,用于声明service。
directive module,用于声明directive。
filter module,用于声明filter。
应用级别的module,依赖上述的module,并且包含初始化的代码。
自带指令
ng-app 、ng-repeat、ng-model,ng-bind、ng-click、
ng-show、ng-change、ng-focus、ng-src、ng-class、
ng-include、ng-mouseover, ng-mouseout, ng-mouseleave,ng-mouseenter
ng-init <div ng-init=“quantity=1;price=5”> 不常用
Databinding及表达式
AngularJS 表达式写在双大括号内:**{{** expression }}
AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙。
AngularJS 将在表达式书写的位置"输出"数据。
AngularJS 表达式 很像 JavaScript 表达式:它们可以包含文字、运算符和变量。
实例 {{ 5 + 5 }} 或 {{ firstName + " " + lastName }}
推荐使用ng-bind, {{ expression **}}**在页面加载完成之前,页面会出现表达式的乱码
<div ng-app=""><p>姓名: {{ firstName + " " + lastName }} </p>
<p>总价: <span ng-bind="quantity * cost“ ></span></p></div>
Controller
<body ng-app="studyApp" ng-controller="frameController">
studyApp.controller("frameController", function ($http, $scope, $timeout, $state, $translate, $filter, $rootScope) {
//省略......
});
一个页面或者一块独立功能区域都可以对应一个controller,即MVC中的C,页面model和相应页面的逻辑处理js,写在这里;
PS:**$scope即当前controller的独立作用域**,相关页面变量和方法可以放在里面,类似于jquery自执行函数的闭包,起到封闭作用域的作用
Factory方式创建的服务,作用就是返回一个有属性有方法的对象。相当于:var f = myFactory();
//创建模型
var app = angular.module('myApp', []);
//通过工厂模式创建自定义服务
app.factory('myFactory', function ()) {
var service = {};
//定义一个Objedct对象
service.name = "王子";
var age; //定义一个私有化的变量
//对私有属性写getter、setter方法
service.setAge = function (newAge) {
age = newAge;
}
service.getAge = function (newAge) {
return age;
}
return service; //返回这个Object对象
});
Service即提供一个服务,可以认为是JAVA里面的一个Utils类,而且是static的,因为只会有一个实例。类似JS的自执行函数并且返回自身对象
provider()是创建service最底层的方式,这也是唯一一个可以使用**.config**()方法配置创建service的方法;(angularjs translate即采用provider方式)
与 factory 和 service 稍有不同的是, provider 必须有一个 $get 方法, $get 方法和 factory 要求是一致的, 即: 先定义一个对象, 给这个对象添加属性和方法, 然后返回这个对象;
provider()不同于service()和factory(),在注入其他的服务的时候不能在function()中依赖注入;
这是唯一能注入到config的service,这样定义的service在你开始注入之前就已经实例化,开发共享的模块的时候常常使用它,能够在使用之前进行配置,
例如 配置服务端的url
例如 配置多语言参数
planAuditApp.config(["$translateProvider",function($translateProvider) {
// 对接菜单URL的多语言参数
var lang = WLJS.getQueryString("lang");
STUDY_COMM.initNGTranslate($translateProvider, lang, [
"studytemplatelist",
"common"
]);
}
]);
Provider定义方法:
app.provider('MyProvider', function () {
this.$get = function () {
var result = {};
result.greeting = 'hello from provider';
teturn result;
}
});
使用方法:
app.controller('myCtrl', function($scope,MyProvider) {
$scope.onclick = function () {
MyProvider('Provider test');
};
});
Factory,Service,Provider区别总结
Factory返回的是一个对象,即设计模式的工厂模式,每次由工厂new一个对象;
Service返回的是this本身,只需要对this的对象及方法进行设置即可,只会实例化一次,相当于一个static的Utils类;
Provider返回的是一个$.get方法,主要作用还是可以config里提前配置,在service和factory之前执行;
Filter****可以用在html标签表达式里面,比如自定义一个字符串过长省略号的过滤器
planControls.filter('cut', function() {
return function(value, wordwise, max, tail) {
if (!value) return '';
max = parseInt(max, 10);
if (!max) return value;
if (value.length <= max) return value;
//原方案未考虑到中英文字符串长度不同
//value = value.substr(0, max);
//wordWise:对于英文等有空格的短语,将残缺的单词去掉
var realValue = '';
var realLength = 0,
len = value.length,
charCode = -1;
for (var i = 0; i < len; i++) {
charCode = value.charCodeAt(i);
if (charCode >= 0 && charCode <= 128)
realLength += 1;
else
realLength += 2;
if (realLength > max)
break;
else
realValue += value.charAt(i);
}
if (wordwise) {
var lastspace = realValue.lastIndexOf(' ');
if (lastspace != -1) {
realValue = realValue.substr(0, lastspace);
}
}
return realValue + (tail || ' …');
};
});
使用:{{** | }}**
<span title="{{plan.name}}" ng-bind="(plan.name | cut:true:20:'...')">
Angular controller通信
此处只涉及同一个dom,单页面,采用事件通信方式
如果一个页面有多个dom,仍旧采用js iframe的方式
Controller通信采用事件方式,事件有两种,emit和broadcast:
broadcast方式与emit方式的区别:
broadcast方式一种广播模式,就是父级发送一个消息时间,子级controller里面监听这个消息事件的函数就会执行;
emit与$broadcast方式相反,是子级controller发布一个消息事件,父级controller监听的函数执行;
注意同一个controller里面都是可以捕获到消息事件的; 但平级之间不能,平级之间可以通过parent中继,先emit再broadcast,不过看有文档说broadcast耗资源过多,路由过于复杂时不宜过多使用
Directive自定义指令,实现html标签的指令解析, 控件
一个例子:
<my-directive show-score="true" ng-model="dataStore.basicPoint"></my-directive>
planControls.directive('myDirective', function() {
return {
restrict: 'E', //表示该directive仅能以element方式使用,即:<basicinfopoing></basicinfopoing> templateUrl: WLJS.getWebRoot() + "/views/study/directive/basicinfopoint.html", replace: true, scope: { //创建一个新的“隔离”scope,通过绑定与父scope通信
ngModel: "=", //双向绑定,外部scope和内部scope的model能够相互改变,字符串和对象都可以
showScore: "="
},
controller: function($scope, $element, $filter) {
$scope.init = function(point) {
if (point > 10 || point < 0) {
return;
}
var cans = $('#basicInfoCanvas');
var ctx = cans[0].getContext('2d');
ctx.clearRect(0, 0, 300, 150);
var bigx = 150;
var bigy = 75;
var bigr = 60;
// 外圆轮廓
ctx.beginPath();
ctx.arc(bigx, bigy, bigr + 15, 0, 2 * Math.PI, false);
ctx.strokeStyle = '#DCDCDC';
ctx.lineWidth = 1;
ctx.stroke();
ctx.closePath();
//省略......
}
$scope.$watch('ngModel', function() {
$scope.init($scope.ngModel);
});
$scope.showAuditScoreWindow = function() {
$scope.$emit("showAuditScoreWindow");
}
}
};
});
restrict:
E: 表示该directive仅能以element方式使用,即:
A: 表示该directive仅能以attribute方式使用,即:<div **my-directive**>
C: 表示该directive仅能以class方式使用,即:<div class="**my-directive**">