原文是这样记录的:
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">×</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('&');
}
未完待续。。。