AngularJS 笔记
使用angularjs已经有一年多的时间,在这期间遇到过不少的问题,但却都没有记录下来,以至于很多时候都得反复去查找相同的资料,所以现在打算从此刻开始积累记录。
fromJson 和 toJson 方法
angular.fromJson()方法是把json转化为对象或者对象数组,源码如下:
function fromJson(json) { return isString(json) ? JSON.parse(json) : json }
angular.toJson()方法是把对象或者数组转化json,源码如下:
function toJson(obj,pretty) { return "undefined" == typeof obj ? undefined : JSON.stringify(obj,toJsonReplacer,pretty ? " " : null) }
promise
angular的promise是由$q提供和构件的,$q提供了一个通过注册一个promise项目来异步执行的方法。
JS中处理异步回调总是非常麻烦,复杂:
// 案例1:在前一个动画执行完成后,紧接着执行下一个动画 $('xx').animate({xxxx},function(){ $('xx').animate({xx},function(){ //do something },1000) },1000)
// 案例2:jquery ajax 异步请求 $.get('url').then(function () { $.post('url1').then(function () { //do something }); });
Promise 有助于开发人员逃离深度嵌套异步回调函数的深渊。Angularjs他通过$q服务提供和构建promise。一个最完整的案例:
var defer1 = $q.defer(); function fun() { var deferred = $q.defer(); $timeout(function () { deferred.notify("notify"); if (iWantResolve) { deferred.resolve("resolved"); } else { deferred.reject("reject"); } },500); return deferred.promise; } $q.when(fun()) .then(function(success){ console.log("success"); console.log(success); },function(err){ console.log("error"); console.log(err); },function(notify){ console.log("notify"); console.log(notify); }) .catch(function(reson){ console.log("catch"); console.log(reson); }) .finally(function(final){ console.log('finally'); console.log(final); });
Promise的调用:$q.when(fun()).then(successCallback,errorCallback,notifyCallback);
简写为:fun().then(successCallback,notifyCallback);
angularjs service封装使用:
angular.module("MyService",[]) .factory('githubService',["$q","$http",function($q,$http){ var getPullRequests = function(){ var deferred = $q.defer(); var promise = deferred.promise; $http.get("url") .success(function(data){ var result = []; for(var i = 0; i < data.length; i++){ result.push(data[i].user); deferred.notify(data[i].user); // 执行状态改变通知 } deferred.resolve(result); // 成功解决(resolve)了其派生的promise。参数value将来会被用作successCallback(success){}函数的参数value。 }) .error(function(error){ deferred.reject(error); // 未成功解决其派生的promise。参数reason被用来说明未成功的原因。此时deferred实例的promise对象将会捕获一个任务未成功执行的错误,promise.catch(errorCallback(reason){...})。 }); return promise; } return { getPullRequests: getPullRequests }; }]); angular.module("MyController",[]) .controller("IndexController",["$scope","githubService",function($scope,githubService){ $scope.name = "dreamapple"; $scope.show = true; githubService.getPullRequests().then(function(result){ $scope.data = result; },function(error){ },function(progress){ // 执行状态通知 notifyCallback }); }]);
$http、$httpProvider服务
https://docs.angularjs.org/ap...$http
https://www.cnblogs.com/keatk...
$http 是angular 封装好的 XMLHttpRequest 请求,angular 的思想偏向restful概念,方法有:GET,POST,PUT,DELTE,PATCH,HEAD等
angular 默认的请求头:
Accept: application/json,text/plain 接受json和text
Content-Type : application/json
如果要修改默认设置的话可以在app.config上做修改
var app = angular.module("app",[]); app.config(function ($httpProvider) { log(angular.toJson($httpProvider.defaults)); $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; $httpProvider.defaults.headers.put["Content-Type"] = "application/x-www-form-urlencoded"; $httpProvider.defaults.headers.patch["Content-Type"] = "application/x-www-form-urlencoded"; });
只要是default的headers,在每次发送请求的时候都会带上。所以如果我们每个请求都有用到一些自定义的header,我们也可以写入在default.headers中。$httpProvider.defaults.headers.common["myHeader"] = "myheaderValue";//common 表示不管任何的 method POST,GET,PUT等
这些default的header是可以在每一次我们发请求的时候通过参数来覆盖掉.另外$http service 也提供了一个defaults的指针 (注: $httpProvider.defaults === $http.defaults )
$httpProvider.defaults.transformRequest & transformResponse
这是angular提供给我们的2个接口,在请求发送前和响应还没有触发callback前对post data 和 response data做一些处理它们是个数组类型,我们可以push一些函数进去 (angular默认对request和response都放入了一个方法,post的时候如果data是对象将json化,响应时如果data是json类型,将解析成对象)。在每一次的请求,我们依然可以覆盖整个数组。
var app = angular.module("app",[]); app.config(function ($httpProvider) { $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; $httpProvider.defaults.transformRequest.shift(); //把angular default的去掉 $httpProvider.defaults.transformRequest.push(function (postData) { //这个function不是依赖注入哦 if (angular.isObject(postData)) { return $.param(postData); //如果postData是对象就把它转成param string 返回,这里借用了jQuery方法 } return postData; }); $httpProvider.defaults.transformResponse.push(function (responseData) { log(angular.toJson(responseData)); //响应的数据可以做一些处理 return "data"; }); }); app.controller("ctrl",function ($scope,$http) { $http({ method: "POST",url: "handle.ashx",data: { key: "value" },transformResponse: [],//每一次请求也可以覆盖default transformResponse: $http.defaults.transformResponse.concat([function () { return "abc" }]) //如果default要保留要concat }).success(function (responseData) { log(responseData === "abc"); //true }); });
$httpProvider.defaults.cache。angular 默认cahce = false,一样可以通过defaults去设置每个请求。我们也可以在每次请求覆盖设置。当同时发送2个没有缓存的请求时,angular也能处理,只发送一次。
var app = angular.module("app",[]); app.config(function ($httpProvider) { $httpProvider.defaults.cache = true; }); app.controller("ctrl",$http) { //并发但是只会发送一个请求 $http.get("handle.ashx"); $http.get("handle.ashx"); //我们可以为每次请求要不要使用缓存或者缓存数据 $http({ url: "handle.ashx",method: "GET",cahce: true }); $http({ url: "handle.ashx",cache : false //强制不使用缓存,即使已存在 }); });
$httpProvider.interceptors
(interceptors 中文是拦截的意思)。除了之前介绍过的 transform 可以对数据做一些处理,angular也提供了另外4个时刻,分别是 onRequest,onRequestFail,onResponse,onResponseFail。让我们做一些而外处理. 比如当我们server返回500的时候,可能我们想做一个通用的alert,或是request fail 的话自动调整一下config在尝试请求等等.
//interceptors是数组,放入的是可以依赖注入的方法哦! $httpProvider.interceptors.push(["$q",function ($q) { return { request: function (config) { //config = {method,postData,url,headers} 等 return config; //返回一个新的config,可以做一些统一的验证或者调整等. },requestError: function (rejection) { return $q.reject(rejection); //必须返回一个promise对象 },response: function (response) { return response; //这里也可以返回 promise,甚至是把它给 $q.reject掉 },responseError: function (rejection) { //rejection = { config,data,status,statusText,headers } return $q.reject(rejection); //必须返回一个promise对象 } }; }]);
transform 的执行次序是这样的 interceptors.request -> transformRequest -> transformResponse -> interceptors.response
判断视图是否渲染完成
// 指令 app.directive('eventNgRepeatDone',function ($timeout) { return { restrict: 'A',link: function (scope,element,attr) { if (scope.$last) { // $timeout(function () { scope.$emit('eventNgRepeatDone'); if ($attrs.ngRepeatDone) { $scope.$apply(function () { $scope.$eval($attrs.ngRepeatDone); }); } //}); } } } }); <!-- 使用 --> <div ng-repeat = "item in list track by $index" event-ng-repeat-done>{{item.name}}</div> app.controller('myCtrl',['$scope',function ($scope) { $scope.$on ('eventNgRepeatDone',function () { // doSomething }); });