因爲網絡等各方面緣由,有時執行一個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