运用AngularJS构建应用时碰到的题目及解决方案(版本为1.3.9)

最近在公司运用用AngularJS(1.3.9)完成了一个项目,在此纪录一下过程当中碰到的题目及解决方案。

运用$http效劳发送ajax要求时后端没法推断要求是XMLHttpRequest

题目及场景
有时候后端会读取要求中headerX-Requested-With字段推断前端的要求是不是为异步要求XMLHttpRequest,在运用$http效劳发送要求时后端却推断为false

缘由
'X-Requested-With' : 'XMLHttpRequest'并不属于规范的header内容,因而Angular不会在header中默许设置该字段。

解决方案
手动在$httpProvider中设置该字段,代码以下:

    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

note:
能够建立一个公用效劳,在设置要领做这个修正,公用效劳注入到每一个module里就一劳永逸了。

运用$http.post()要领参数范例不准确

题目及场景
在angular中,运用$http.post()要领提交数据时,发明所带参数并不是Form Data,而是JSON对象,致使效劳器没法运用平常要领准确猎取参数,而运用jQuery的$.post()要领却能够准确猎取。

缘由
二者的post对header的处置惩罚有所不同,jQuery会把作为JSON对象的myData序列化,比方:

    var myData = { a : 1, b : 2 };
    // jQuery在post数据之前会把myData转换成字符串:"a=1&b=2"

angular明显没做这个处置惩罚。

解决方案
修正Angular的$httpProvider的默许处置惩罚,代码以下:

    $httpProvider.defaults.transformRequest = function(obj){
        var str = [];
        for(var p in obj) {
            str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
        }
        return str.join("&");
    };

    $httpProvider.defaults.headers.post = {
        'Content-Type': 'application/x-www-form-urlencoded'
    };

note:
一样应当在公用效劳中做此修正。

挪用$scope.$apply(fn)更新视图时报错$rootScope:inprog

题目及场景
在更新$scope上的model数据时,假如是在digest监听外,会发明视图并没有自动更新,因而手动挪用$scope.$apply(fn)要领关照视图举行更新,却发明有时候会报错$rootScope:inprog

缘由
该毛病缘由是在历程当中$scope.$apply(fn)正在实行,不能在此基础上反复挪用该要领。

解决方案
能够在挪用该要领时做一个平安检测,封装代码以下:

    $scope.safeApply = function(fn) {
        var phase = this.$root.$$phase;
        if (phase === '$apply' || phase === '$digest') {
            if (fn && (typeof(fn) === 'function')) {
                fn();
            }
        } else {
            this.$apply(fn);
        }
    };

note:
$$phase变量是scope中的一个内部属性,假如为null或许undefined则申明历程中没有$apply要领在运转,则能够直接挪用,不然直接实行入参要领。

增加一致阻拦器对ajax的要求或返回做处置惩罚

题目及场景
我碰到的场景是在发送异步要求时,后端会先推断用户是不是已登录,假如未登录则会在responseheader中增加一个redirecturl字段,前端读取该字段掌握页面跳转到该url,我起首想到的解决方案就是前端须要做一个一致阻拦器,对一切异步要求的response举行阻拦。

解决方案
经由过程看Angular中$httpProvider部份的源码解释,发明了阻拦器的几种写法,我挑选的写法源码解释以下:

    *   // register the interceptor as a service
    *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
    *     return {
    *       // optional method
    *       'request': function(config) {
    *         // do something on success
    *         return config;
    *       },
    *
    *       // optional method
    *      'requestError': function(rejection) {
    *         // do something on error
    *         if (canRecover(rejection)) {
    *           return responseOrNewPromise
    *         }
    *         return $q.reject(rejection);
    *       },
    *       // optional method
    *       'response': function(response) {
    *         // do something on success
    *         return response;
    *       },
    *
    *       // optional method
    *      'responseError': function(rejection) {
    *         // do something on error
    *         if (canRecover(rejection)) {
    *           return responseOrNewPromise
    *         }
    *         return $q.reject(rejection);
    *       }
    *     };
    *   });
    *   $httpProvider.interceptors.push('myHttpInterceptor');

我阻拦response的代码以下:

    commonService.factory('redirectInterceptor', function(){
        return {
            'response': function(response) {
                if(response.headers().redirecturl) {
                    window.location.href = response.headers().redirecturl;
                }
                return response;
            }
        };
    });

    $httpProvider.interceptors.push('redirectInterceptor');

note
末了一行示意将该阻拦器登记到$httpProvider的阻拦器中,一样应当写在公用效劳的设置要领当中。

controller之间的通讯题目

题目及场景
当有两个视图分别由两个controller掌握时,个中一个视图发生变化,需关照另一个视图发生了此变化。

解决方案
总的来说,Angular中掌握器通讯有三种处置惩罚要领:

  • 应用作用域继续的体式格局 即子掌握器继续父掌握器中的内容;

  • 基于事宜的体式格局 即$on,$emit,$boardcast这三种要领;

  • 效劳体式格局 写一个效劳的单例然后经由过程注入来运用。

我挑选了末了一种要领,示例代码以下:

    //JS
    var app = angular.module('myApp', []);
    app.factory('instance', function(){
        return {};
    });
    app.controller('MainCtrl', function($scope, instance) {
        $scope.change = function() {
        instance.name = $scope.test;
        };
    });
    app.controller('sideCtrl', function($scope, instance) {
        $scope.add = function() {
            $scope.name = instance.name;
        };
    });
    //html
    <div ng-controller="MainCtrl">
        <input type="text" ng-model="test" />
        <div ng-click="change()">click me</div>
    </div>
    <div ng-controller="sideCtrl">
        <div ng-click="add()">my name </div>
    </div>

note:
在Angular中效劳是一个单例,所以在效劳中天生一个对象,该对象就能够应用依靠注入的体式格局在一切的掌握器中同享。
假如不是经由过程点击发生变化,还可连系$scope.$watch()要领来举行通讯。
其他两种要领可参考站内文章:AngularJS掌握器controller怎样通讯?

结语

以上为我在编写一个angular应用时碰到的题目及解决方案,纪录并分享出来,迎接人人斧正!

    原文作者:llp要变身
    原文地址: https://segmentfault.com/a/1190000004318703
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞