• 前端遇到的一些坑


    1、 angular强制清除浏览器缓存

     原文是这样记录的:

    Caching

    $http responses are not cached by default. To enable caching, you must set the config.cache value or the default cache value to TRUE or to a cache object (created with $cacheFactory). If defined, the value of config.cache takes precedence over the default cache value.

    In order to:

    • cache all responses - set the default cache value to TRUE or to a cache object
    • cache a specific response - set config.cache value to TRUE or to a cache object

    If caching is enabled, but neither the default cache nor config.cache are set to a cache object, then the default $cacheFactory("$http")object is used.

    The default cache value can be set by updating the $http.defaults.cache property or the $httpProvider.defaults.cache property.

    When caching is enabled, $http stores the response from the server using the relevant cache object. The next time the same request is made, the response is returned from the cache without sending a request to the server.

    Take note that:

    • Only GET and JSONP requests are cached.
    • The cache key is the request URL including search parameters; headers are not considered.
    • Cached responses are returned asynchronously, in the same way as responses from the server.
    • If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.
    • A cache-control header on the response does not affect if or how responses are cached.

    翻译:

    缓存

    $http响应默认不是缓存的。为了能够缓存,必须设置config.cache的值,或者默认的cache值为TRUE,或者创建缓存对象(由$cacheFactory创建)。如果定义了,配置的cache值比默认的cache值优先级高。

    为了:

    • 缓存所有响应 - 设置缓存值为TRUE或者设置缓存对象
    • 缓存指定响应 - 设置config.cache的值为TRUE或者设置缓存对象

    如果缓存生效,但是既没有设置默认cache,也没有设置config.cache为缓存对象,那么默认的 $cacheFactory("$http")将会使用。

    默认的cache值可以通过更新$http.defaults.cache属性或 $httpProvider.defaults.cache属性来设置

    当缓存生效时, $http通过使用相关缓存对象,存储来自服务器的响应。如果下一次执行了同样的请求,响应是来自缓存,而不是发送一个请求至服务端。

    注意:

    • 只有GET和JSONP请求有缓存
    • 缓存的key是请求的URL,包含搜索参数,不包含头部
    • 缓存响应是通过异步返回的,与通过服务端响应的方式是一样的。
    • 如果执行多个同样的请求,使用同样的缓存,缓存不是一直存在的,一个请求发送到服务端,剩下的请求返回同样的响应。
    • 响应头的cache-control不会影响是否换存和如何缓存的

    2、记录路由切换时,记录路由的变化

    通过angularjs自带的$locationChangeStart

      .run(['$rootScope', '$window', '$location', '$log', function ($rootScope, $window, $location, $log) {
        var locationChangeStartOff = $rootScope.$on('$locationChangeStart', function(event , next, current) {
          $log.log('locationChangeStart');
          $log.log(arguments);
        });
    
      }])  

    如果请求的参数放在angular自带的params中,并不能很好滴获取页面的请求参数,所以上面的这种解决方案并不是很有效。

    只能另想其法了。

    因为页面的请求URL变化,是通过点击来触发的,可以在触发URL状态变化后,记录状态变化的请求URL,并将请求的URL放在sessionStorage中。

    比如:

    //切换待办已办已建
        $scope.changeTable=function(code){
          $scope.nowCode=code;
          $scope.getOrderDate(pNum,pSize,$scope.nowCode,$scope.status,$scope.searchInfo,$scope.whichOrder);
          //获取当前请求的URL,并保存至sessionStorage中
          sessionStorage.setItem('orderUrl', JSON.stringify({
            url:$location.absUrl(),
            pageNum:pNum,
            pageSize:pSize,
            code:code,
            type:$scope.status,
            keyWord:$scope.searchInfo,
            orderBy:$scope.whichOrder}));
          $rootScope.orderAbsUrl = JSON.parse(sessionStorage.getItem('orderUrl'));
          console.log($rootScope.orderAbsUrl);
        };
    

    下载相应的stateEvent.js文件,就可以解决相应的问题。

     3、ng-click获取当前点击对象,获取自定义属性值

    <span class="operate">
    <i class="iconfont icon-beifen_download" data-value="Windows Server 2008 R2" ng-click="downLoad($event.target)" title="下载"></i>
    </span>
    $scope.downLoad = function (evt) {
          var fileName = $(evt).data('value');
          console.log(fileName);
        };/  

    4、bootstrap模态框清除缓存

    bootstrap 模态框清除缓存,一直不知道如何解决问题,

    网上常见的解决方案是:

         $('body').on('hidden.bs.modal', '.modal', function () {
            $(this).removeData('bs.modal');
          });  

    但是对于的情况不太有效

    <div class="modal allocateModel" tabindex="-1" role="dialog" id="userSysAllocate">
        <div class="modal-dialog allocateDialog" role="document">
            <div class="modal-content allocateContent">
                <div class="modal-header allocateHeader">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title">分配备份系统</h4>
                </div>
                <div class="modal-body allocateBody" id="allocateContent">
                    <span class="selectHeader">请选择一个或多个备份系统</span>
                    <div class="selectBtn">
                        <div class="forSelect">
                            <input type="checkbox" ng-model="allSelected" ng-checked="allSelected" class="checkIpt" ng-click="selectAll()" value="全选"><span class="selectEle">全选</span>
                        </div>
                        <ul>
                            <li class="roleSelect" ng-repeat="rUser in rUsers track by $index" style="float: left;">
                                <input type="checkbox" ng-disabled="rUser.creatorId == userBackupId" ng-checked="rUser.relativeState" ng-model="rUser.relativeState" name="chosed" ng-click="allChoose()" class="allCheck checkIptOne" value="{{rUser.systemPkId}}"><span class="selectEle slectRht">{{rUser.systemName}}</span>
                            </li>
                        </ul>
                    </div>
                </div>
                <div class="modal-footer allocateFooter">
                    <button type="button" class="btn btn-default allocateCancle" data-dismiss="modal">取 消</button>
                    <button type="button" class="btn btn-primary allocateConfirm" ng-click="allocateSubmit(userBackupId)">确 定</button>
                </div>
            </div>
        </div>
    </div>

    对应的全选和反选操作是通过原生的Dom操作来实现的,但除了全选的input选择框,剩下都是通过ng-repeat后台获取的,这种是采用的angular方式,也就是angular和原生的Dom操作混用,刚开始还觉得没有问题,后发现全选和反选后,点击取消,再次打开模态框,勾选的没有取消。这就是混用导致的问题。

    所以解决方案就是要么就全部使用原生的dom操作,要么就全部使用angular方式。避免混用出现的不可预测的问题。

    下面是开始的解决方案,也是出现问题的

          $scope.selectAll = function () {
            var objSelect = document.getElementsByClassName('allCheck'),
              len = objSelect.length;
            if($scope.allSelected) {
              for(var i=0; i<len; i++) {
                objSelect[i].checked = true;
              }
            } else {
              for(var i=0; i<len; i++) {
                objSelect[i].checked = false;
              }
            }
          };
          $scope.allChoose = function () {
            var objChoose = document.getElementsByName('chosed'),
              objTrue = [],
              len = objChoose.length;
            for(var i=0; i<len; i++) {
              objTrue.push(objChoose[i].checked);
            }
            var checkRes = objTrue.every(function(item){ return item == true });
            $scope.allSelected = checkRes == true ? true : false;
          };  

    采用纯angular方式  

            $scope.selectAll = function () {
                var len = $scope.rUsers ? $scope.rUsers.length : 0;
                if($scope.allSelected) {
                    for(var i=0; i<len; i++) {
                      $scope.rUsers[i].relativeState = true;
                    }
                } else {
                    for(var i=0; i<len; i++) {
                      $scope.rUsers[i].relativeState = false;
                    }
                }
            };
            $scope.allChoose = function () {
              var len = $scope.rUsers ? $scope.rUsers.length : 0,
                objTrue = [];
              for(var i=0; i<len; i++) {
                  objTrue.push($scope.rUsers[i].relativeState);
              }
              var checkRes = objTrue.every(function(item){ return item == true });
              $scope.allSelected = checkRes == true ? true : false;
            };
    
            $('body').on('hidden.bs.modal', '.modal', function () {
              $(this).removeData('bs.modal');
              $scope.sysPrivilege = [];
              $scope.allSelected = false;
            });
    

    5、使用splice删除数组中符合条件的项

    删除符合条件的项,使用splice来删除,采用倒序的方式,不用break。

    如:

    var str = ['sidebar.roleList{"#":null','sidebar.modifyPassword{"#":null','sidebar.modifyPassword{"#":null'];

    for(var i=str.length;i--;){
    if(str[i].indexOf('sidebar.modifyPassword') != -1){
    str.splice(i,1);
    }

    }
    console.log(str); 

    结果见上。

    6、AngularJS下$http上传文件(AngularJS file upload/post file)

    angularjs上传多个文件,按照网上提示的设置headers: {Content-Type': undefined}和transformRequest: angular.identity,但是仍然提示失败,后来又寻找到另外的一种解决方案:

    $http({
    
      method:'POST',
      url: 'url',
      headers: { 'Content-Type': undefined },
      data: data,
      transformRequest: (data, headersGetter) => {
        let formData = new FormData();
        angular.forEach(data, function (value, key) {
          formData.append(key, value);
        });
        return formData;
       }
    })
    .then(function(response, header, config, status) {
       handle(response, resovle, reject);
     }, function(response, header, config, status) {
         reject('接口访问异常');
    });
    

     不支持箭头函数,仍然提示上传附件失败,改成下面的格式就可以了。不知道是什么原因。

        function uploadFile(url, data) {
          return $q(function(resovle, reject) {
            $http({
              url: url,
              method: 'POST',
              data: data,
              headers: {'Content-Type': undefined},
              transformRequest: function (data, headersGetter) {
                var formData = new FormData();
                angular.forEach(data, function (value, key) {
                  formData.append(key, value);
                });
                return formData;
              }
            }).then(function(response, header, config, status) {
              handle(response, resovle, reject);
            }, function(response, header, config, status) {
              reject('接口访问异常');
            })
          })
        }
    

    7、点击空白区域或非目标区域,关闭气泡,或弹出模态框

    下面是jQuery写法

    $(document).mouseup(function(e){
      var _con = $(' 目标区域 ');   // 设置目标区域
      if(!_con.is(e.target) && _con.has(e.target).length === 0){ // Mark 1
        some code...   // 功能代码
      }
    });
    /* Mark 1 的原理:
    判断点击事件发生在区域外的条件是:
    1. 点击事件的对象不是目标区域本身
    2. 事件对象同时也不是目标区域的子元素
    */  

      

    对于angularjs而言,需要注入$document

    $document.mouseup(function(e){
          var _con = angular.element(".notice-operate");   // 设置目标区域
          if(!_con.is(e.target) && _con.has(e.target).length === 0){ // Mark 1
            $scope.close_popups(); // 功能代码
          }
        });
    

    8、$stateParams获取不到值,返回undefined。

    找了好久,不知原因所在,后来在在网上查到依赖注入输入不一致导致,修改成一致,问题解决了,代码还是要规范。

    angular.module('frontierApp.userManage', ['ui.router', 'frontierApp.pagination', 'angular-popups'])
      .config(['$stateProvider', userConfig])
      .controller('UserListCtrl', ['UserManageService', '$rootScope', '$state','$scope', '$stateParams', '$document', 'BASE_URL', UserListCtrl])
      .controller('UserDetailCtrl', ['UserManageService', '$rootScope', '$state','$scope', '$http', '$stateParams', UserDetailCtrl])
      .controller('UserEditCtrl', ['UserManageService', '$rootScope','$state','$scope', '$http', '$stateParams', UserEditCtrl])
      .controller('UserCreateCtrl', ['UserManageService', '$rootScope','$state','$scope', '$stateParams', UserCreateCtrl]);
    
    function UserDetailCtrl(UserManageService, $rootScope, $state, $scope, $stateParams) {
    /*代码*/
    }  

     

    改成如下

    angular.module('frontierApp.userManage', ['ui.router', 'frontierApp.pagination', 'angular-popups'])
      .config(['$stateProvider', userConfig])
      .controller('UserListCtrl', ['UserManageService', '$rootScope', '$state','$scope', '$stateParams', '$document', 'BASE_URL', UserListCtrl])
      .controller('UserDetailCtrl', ['UserManageService', '$rootScope', '$state','$scope','$stateParams', UserDetailCtrl])
      .controller('UserEditCtrl', ['UserManageService', '$rootScope','$state','$scope','$stateParams', UserEditCtrl])
      .controller('UserCreateCtrl', ['UserManageService', '$rootScope','$state','$scope', '$stateParams', UserCreateCtrl]);
    
    function UserDetailCtrl(UserManageService, $rootScope, $state, $scope, $stateParams) {
    /*代码*/
    }  
    

      

    9,IE10浏览器导出,报400错误。

    查了下,http请求报400错误的原因:

    1)前端提交数据的字段名称或者是字段类型和后台的实体类不一致,导致无法封装;

    2)前端提交的到后台的数据应该是json字符串类型,而前端没有将对象转化为字符串类型;

    导出代码

    location.href = BASE_URL + '/user/userinfos/xls?idOrName='+ keyword;  

      

    解决方法:

    var keyword = $scope.serkey ? $scope.serkey : "";
    var data = {idOrName : encodeURI(keyword)};
    location.href = BASE_URL + '/user/userinfos/xls' + "?" + jsonToUrlStr(data);  

     

    其中jsonToUrlStr函数见下:

        function jsonToUrlStr(data) {
          var strArr = [];
          for (var m in data) {
            strArr.push(m + '=' + data[m]);
          }
          return strArr.join('&');
        }
    

      

      

      

    未完待续。。。  

  • 相关阅读:
    深港DJ好听的歌曲
    电调的相关知识
    CAD画图技巧经验
    第一期周二航拍视频分享 2017/07/10
    网站资料
    如何读懂零件图
    航拍技巧经验总汇
    乐迪AT9
    机器学习、数据挖掘、计算机视觉等领域经典书籍推荐
    Eclipse调试Java程序技巧
  • 原文地址:https://www.cnblogs.com/WaTa/p/7474352.html
Copyright © 2020-2023  润新知