由于网络等各方面原因,有时执行一个ajax操作时有时需要等待比较长的时间,如果不进行特殊处理就无法知道当前操作的状态,严重影响用户体验。
比较常见的解决方案是执行可能的长操作前先打开一个蒙版,覆盖页面,通过动画指示当前页面处于执行状态,获得返回结果后在关闭蒙版。这种方式虽然可以很清晰的展现正在等待操作结果的状态,但是对于网络条件比较好,操作结果很快就返回的情况,会给用户造成一种页面闪烁的感觉,也会影响用户体验。
为了解决上面的问题,考虑利用angular的directive对执行长操作时需要进行控制的元素进行设置,实现以元素为单位进行页面状态的控制。
需要进行状态控制的元素有几类:1、input元素,执行长操作时它们应该处于disabled状态;2、button等发起操作的元素,它们应该出于disabled的状态,同时发起正在执行的长操作的元素应该出于running的状态,例如:通过动画。
实现思路如下:
1、定义directive,tms-lock
app = angular.module('app', []);
app.directive('tmsLock', function() {
return {
restrict: 'A',
scope: {
lock: '=tmsLock'
},
priority: 99,
compile: function(tElem, tAttrs) {
var originalFn, lockableFn;
if (tAttrs.tmsLockPromoter === 'Y' && tAttrs.ngClick) {
originalFn = tAttrs.ngClick;
lockableFn = '__lockable__' + originalFn;
tAttrs.ngClick = lockableFn;
}
return {
pre: function(scope, iElem, iAttrs) {
if (lockableFn) {
scope.$parent[lockableFn.replace(/\(.*\)/, '')] = function() {
var eleIndicator = document.createElement('div');
eleIndicator.classList.add('indicator');
scope.lock = true;
iElem.addClass('tms-lock-running');
iElem.append(eleIndicator);
scope.$parent[originalFn.replace(/\(.*\)/, '')].apply(scope, arguments).then(function() {
scope.lock = false;
iElem.removeClass('tms-lock-running');
iElem[0].removeChild(eleIndicator);
});
};
}
scope.$watch('lock', function(locked) {
if (locked === true) {
iElem.addClass('tms-locked');
iAttrs.$set('disabled', true);
} else if (locked === false) {
iElem.removeClass('tms-locked');
iAttrs.$set('disabled', undefined);
}
});
}
}
}
}
});
app.controller('ctrl', ['$scope', '$q', '$timeout', function($scope, $q, $timeout) {
$scope.lock = false;
$scope.longFn = function() {
var defer;
defer = $q.defer();
$timeout(function() {
defer.resolve();
}, 10000);
return defer.promise;
};
$scope.otherFn = function() {
// do nothing
};
}]);
2、设置运行状态的样式
@keyframes tmsRunning{
0%{transform:rotate(0deg);}
12%{transform:rotate(45deg);}
25%{transform:rotate(90deg);}
37%{transform:rotate(135deg);}
50%{transform:rotate(180deg);}
62%{transform:rotate(225deg);}
75%{transform:rotate(270deg);}
87%{transform:rotate(315deg);}
100%{transform:rotate(360deg);}
}
@-webkit-keyframes tmsRunning{
0%{-webkit-transform:rotate(0deg);}
12%{-webkit-transform:rotate(45deg);}
25%{-webkit-transform:rotate(90deg);}
37%{-webkit-transform:rotate(135deg);}
50%{-webkit-transform:rotate(180deg);}
62%{-webkit-transform:rotate(225deg);}
75%{-webkit-transform:rotate(270deg);}
87%{-webkit-transform:rotate(315deg);}
100%{-webkit-transform:rotate(360deg);}
}
@-moz-keyframes tmsRunning{
0%{-moz-transform:rotate(0deg);}
12%{-moz-transform:rotate(45deg);}
25%{-moz-transform:rotate(90deg);}
37%{-moz-transform:rotate(135deg);}
50%{-moz-transform:rotate(180deg);}
62%{-moz-transform:rotate(225deg);}
75%{-moz-transform:rotate(270deg);}
87%{-moz-transform:rotate(315deg);}
100%{-moz-transform:rotate(360deg);}
}
@-o-keyframes tmsRunning{
0%{-o-transform:rotate(0deg);}
12%{-o-transform:rotate(45deg);}
25%{-o-transform:rotate(90deg);}
37%{-o-transform:rotate(135deg);}
50%{-o-transform:rotate(180deg);}
62%{-o-transform:rotate(225deg);}
75%{-o-transform:rotate(270deg);}
87%{-o-transform:rotate(315deg);}
100%{-o-transform:rotate(360deg);}
}
.btn.tms-lock-running {
position: relative;
}
.btn.tms-lock-running .indicator::after {
content: '';
position: absolute;
left: 50%;
top: 4px;
bottom: 4px;
width: 4px;
margin-left: -2px;
background: #333;
}
.btn.tms-lock-running .indicator {
position: absolute;
left: 50%;
top: 50%;
margin-left: -1em;
margin-top: -1em;
border-radius: 1em;
width: 2em;
height: 2em;
border: 2px solid #333;
background: #fff;
animation: tmsRunning 1s infinite;
-webkit-animation: tmsRunning 1s infinite;
-moz-animation: tmsRunning 1s infinite;
-o-animation: tmsRunning 1s infinite;
}
3、给需要锁定的元素添加属性
<input class='form-control' type='text' tms-lock="lock">
<button class='btn btn-default' tms-lock="lock" tms-lock-promoter="Y" ng-click="longFn()">long action</button>
<button class='btn btn-default' tms-lock="lock" ng-click="otherFn()">other action</button>
其他仍在考虑的问题:1、是否允许用户主动解除页面锁定状态?2、是否需要对硬的页面导航操作,例如:后退,进行控制?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。