因为网络等各方面缘由,有时执行一个ajax操做时有时须要等待比较长的时间,若是不进行特殊处理就没法知道当前操做的状态,严重影响用户体验。web
比较常见的解决方案是执行可能的长操做前先打开一个蒙版,覆盖页面,经过动画指示当前页面处于执行状态,得到返回结果后在关闭蒙版。这种方式虽然能够很清晰的展示正在等待操做结果的状态,可是对于网络条件比较好,操做结果很快就返回的状况,会给用户形成一种页面闪烁的感受,也会影响用户体验。ajax
为了解决上面的问题,考虑利用angular的directive对执行长操做时须要进行控制的元素进行设置,实现以元素为单位进行页面状态的控制。promise
须要进行状态控制的元素有几类:一、input元素,执行长操做时它们应该处于disabled状态;二、button等发起操做的元素,它们应该出于disabled的状态,同时发起正在执行的长操做的元素应该出于running的状态,例如:经过动画。网络
实现思路以下:
一、定义directive,tms-lockapp
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 }; }]);
二、设置运行状态的样式动画
@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; }
三、给须要锁定的元素添加属性rest
<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>
示例code
其余仍在考虑的问题:一、是否容许用户主动解除页面锁定状态?二、是否须要对硬的页面导航操做,例如:后退,进行控制?orm