资讯专栏INFORMATION COLUMN

基于angular实现等待长操作时锁定页面

2shou / 651人阅读

摘要:由于网络等各方面原因,有时执行一个操作时有时需要等待比较长的时间,如果不进行特殊处理就无法知道当前操作的状态,严重影响用户体验。为了解决上面的问题,考虑利用的对执行长操作时需要进行控制的元素进行设置,实现以元素为单位进行页面状态的控制。

由于网络等各方面原因,有时执行一个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、给需要锁定的元素添加属性



示例

其他仍在考虑的问题:1、是否允许用户主动解除页面锁定状态?2、是否需要对硬的页面导航操作,例如:后退,进行控制?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78539.html

相关文章

  • 最近遇到的前端面试题(2017.03.08更新版)

    摘要:通过管理组件通信通过驱动视图比较差异进行更新操作作者第七页链接来源知乎著作权归作者所有,转载请联系作者获得授权。达到无刷新的效果。对象的状态不受外界影响。对象代表一个异步操作,有三种状态进行中已完成,又称和已失败。 以下问题解释非本人原创,是根据面试经验整理后觉得更容易理解的解释版本,欢迎补充。 一. 输入url后的加载过程 从输入 URL 到页面加载完成的过程中都发生了什么 计算机...

    linkFly 评论0 收藏0
  • 最近遇到的前端面试题(2017.03.08更新版)

    摘要:通过管理组件通信通过驱动视图比较差异进行更新操作作者第七页链接来源知乎著作权归作者所有,转载请联系作者获得授权。达到无刷新的效果。对象的状态不受外界影响。对象代表一个异步操作,有三种状态进行中已完成,又称和已失败。 以下问题解释非本人原创,是根据面试经验整理后觉得更容易理解的解释版本,欢迎补充。 一. 输入url后的加载过程 从输入 URL 到页面加载完成的过程中都发生了什么 计算机...

    Nosee 评论0 收藏0
  • 最近遇到的前端面试题(2017.03.08更新版)

    摘要:通过管理组件通信通过驱动视图比较差异进行更新操作作者第七页链接来源知乎著作权归作者所有,转载请联系作者获得授权。达到无刷新的效果。对象的状态不受外界影响。对象代表一个异步操作,有三种状态进行中已完成,又称和已失败。 以下问题解释非本人原创,是根据面试经验整理后觉得更容易理解的解释版本,欢迎补充。 一. 输入url后的加载过程 从输入 URL 到页面加载完成的过程中都发生了什么 计算机...

    刘东 评论0 收藏0
  • mysql锁机制浅析(1)

    摘要:当多个客户端并发访问同一个数据的时候,为了保证数据的一致性,数据库管理系统会自动的为该数据加锁解锁,这种被称为隐式锁。 mysql最初是希望设计出一种独立于各种存储引擎的锁定机制,mysql存储引擎的设计者是建立在任何表在同一时刻只允许单个线程对其进行访问(包括读)这样的假设的基础之上的!很明显,现在的mysql并不是这个样子的,因为mysql如今已经发展成为了一款多用户、多线程的my...

    jiekechoo 评论0 收藏0
  • 实现页面加载等待动画很简单吗?

    摘要:二基于上面的测试,实现页面加载动画理想的方式是什么先定好目标尽快让用户看到变化,不要让用户以为页面已经不响应,再逐步加载内容。页面上方加载动画的定义和页面元素,提供异步加载页面元素和文件的。 在手机上打开页面时,经常会因为网络不好导致需要较长的加载时间,如果这段时间内只是显示一个白板,用户体验非常不好。通常的解决方案就是完整打开页面前给用户展示一个加载动画,让用户能够看到页面还活着呢。...

    bawn 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<