zoukankan      html  css  js  c++  java
  • ng-style 的坑

    本文地址:http://www.cnblogs.com/jying/p/5633203.html 

    熟悉 angular 的前端对ng-style 一定不陌生,这个家伙可以绑定一个函数,使得我们可以在函数中根据不同的参数返回不同的样式,如下是一个简单的实例:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body onselectstart='return false'>
        <div ng-app="myApp" ng-controller="myCtrl" style="overflow-wrap:break-word;">
            <span ng-repeat="idx in data" ng-style="setStyle(idx)">
                {{idx+','}}
            </span>
        </div>
    
        <script type="text/javascript">
            var app = angular.module('myApp', []);
            app.controller('myCtrl', function($scope) {
                $scope.data = [];
                for(var i=1;i<=10000;i++){
                    $scope.data.push(i);
                }
    
                $scope.setStyle = function(idx){
                    switch(idx%4){
                        case 1:return {"color":"red"};
                        case 2: return {"color":"chartreuse"};
                        case 3:return {"color":"yellow"};
                        case 0:return {"color":"blue"};
                        default : return {};
                    }
                }
    
            });
        </script>
    </body>
    </html>
    ng-style 绑定文字颜色

    在该实例中,我们通过 $index 绑定不同的文字颜色,是不是感觉很方便呢,程序猿和代码其乐融融,相处的很好嘛O(∩_∩)O

    直到有一天......业务提出这么一个需求:在成千上万的 span 上拖动鼠标选择区域设置背景色!

    拖动鼠标嘛,简单!我们有 ng-mouseenter、ng-mouseleave、ng-mousemove、ng-mouseup 、ng-mousedown!挽起袖子搞起! 

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body onselectstart='return false' style="-moz-user-select:none;">
        <div ng-app="myApp" ng-controller="myCtrl" style="overflow-wrap:break-word;">
            <span ng-repeat="idx in data" ng-style="setStyle(idx)" 
                ng-mousedown="mousedown($event)" ng-mouseup="mouseup($event)" ng-mouseenter="mouseenter($event)">
                {{idx+','}}
            </span>
        </div>
    
        <script type="text/javascript">
            var app = angular.module('myApp', []);
            app.controller('myCtrl', function($scope) {
                $scope.data = [];
                for(var i=1;i<=10000;i++){
                    $scope.data.push(i);
                }
    
                $scope.setStyle = function(idx){
                    switch(idx%4){
                        case 1:return {"color":"red"};
                        case 2: return {"color":"chartreuse"};
                        case 3:return {"color":"yellow"};
                        case 0:return {"color":"blue"};
                        default : return {};
                    }
                }
    
                //识别鼠标是否按下
                $scope.isdown = false;
                //鼠标按下
                $scope.mousedown = function(e){
                    $scope.isdown = true;
                }
                //鼠标抬起
                $scope.mouseup = function(e){
                    $scope.isdown = false;
                }
                //鼠标进入
                $scope.mouseenter = function(e){
                    if($scope.isdown){
                        console.log(e.target.style.backgroundColor = "#eeeeee");
                    }
                }
            });
        </script>
    </body>
    </html>
    ng-mouse 事件拖动鼠标绑定背景色

    好像也没有什么问题嘛 →.→ 其实业务给的需求场景比这个复杂的多,这里只是举例说明所以目前没有感觉出现问题,那么ng-style 是在什么时候绑定控件的 style 样式呢?于是给$scope.setStyle 添加输出:console.log(idx);  结果刚才较流畅的界面卡出翔了 ←.← 

    好吧,我们把数字改小点看看效果 ↓ . ↓

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body onselectstart='return false' style="-moz-user-select:none;">
        <div ng-app="myApp" ng-controller="myCtrl" style="overflow-wrap:break-word;background-color: #dddddd;">
            <span ng-repeat="idx in data" ng-style="setStyle(idx)" 
                ng-mousedown="mousedown($event)" ng-mouseup="mouseup($event)" ng-mouseenter="mouseenter($event)">
                {{idx+','}}
            </span>
        </div>
    
        <script type="text/javascript">
            var app = angular.module('myApp', []);
            app.controller('myCtrl', function($scope) {
                $scope.data = [];
                for(var i=1;i<=100;i++){
                    $scope.data.push(i);
                }
    
                $scope.setStyle = function(idx){
                    console.log(idx + " -- "+ (new Date()).getMilliseconds());
                    switch(idx%4){
                        case 1:return {"color":"red"};
                        case 2: return {"color":"chartreuse"};
                        case 3:return {"color":"yellow"};
                        case 0:return {"color":"blue"};
                        default : return {};
                    }
                }
    
                //识别鼠标是否按下
                $scope.isdown = false;
                //鼠标按下
                $scope.mousedown = function(e){
                    $scope.isdown = true;
                }
                //鼠标抬起
                $scope.mouseup = function(e){
                    $scope.isdown = false;
                }
                //鼠标进入
                $scope.mouseenter = function(e){
                    if($scope.isdown){
                        console.log(e.target.style.backgroundColor = "red");
                    }
                }
            });
        </script>
    </body>
    </html>
    ng-style 函数中写入console.log

    按下 F12 查看控制台 ,鼠标移入数字区,可以看到console.log 不停的输出,也就是说此时 ng-style 是不停的重复绑定的,这显然是耗费资源的,在某些实时要求高的界面就会导致卡顿现象,为了避免这种重复的资料消耗决定换个方式绑定style,且要只绑定一次,想来想去决定还是用 for 遍历控件绑定

                $scope.data = [];
                for(var i=1;i<=100;i++){
                    $scope.data.push(i);
                }
                var spans = document.querySelectorAll("span");
                for(var j=0;j<spans.length;j++){
                    var span = spans[j];
                    console.log(span);
                }

    然而这样获取到 spans 为[] ,因为此时ng-repeat 还没有渲染完 span ,根据js单线程原理,此时应该用$timeout(function(){},0); 原理请阅读:setTimeout 的黑魔法 

    看来以后要弃用 ng-style 的使用了。

    全部实现代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body onselectstart='return false' style="-moz-user-select:none;">
        <div ng-app="myApp" ng-controller="myCtrl" style="overflow-wrap:break-word;background-color: #dddddd;">
            <!--<span ng-repeat="idx in data" ng-style="setStyle(idx)" 
                ng-mousedown="mousedown($event)" ng-mouseup="mouseup($event)" ng-mouseenter="mouseenter($event)">
                {{idx+','}}
            </span>-->
    
            <span ng-repeat="idx in data" test-index ={{idx}}
                ng-mousedown="mousedown($event)" ng-mouseup="mouseup($event)" ng-mouseenter="mouseenter($event)">
                {{idx+','}}
            </span>
        </div>
    
        <script type="text/javascript">
            var app = angular.module('myApp', []);
            app.controller('myCtrl', function($scope,$timeout) {
                $scope.data = [];
                for(var i=1;i<=100;i++){
                    $scope.data.push(i);
                }
                $timeout(function(){
                    var spans = document.querySelectorAll("span");
                    for(var j=0;j<spans.length;j++){
                        var span = spans[j];
                        console.log(span.style.color =$scope.setStyle(span.attributes["test-index"].value));
                    }
                },0);
    
                $scope.setStyle = function(idx){
                    console.log(idx + " -- "+ (new Date()).getMilliseconds());
                    switch(idx%4){
                        case 1:return "red";
                        case 2: return "chartreuse";
                        case 3:return "yellow";
                        case 0:return "blue";
                        default : return "#fff";
                    }
                }
    
                //识别鼠标是否按下
                $scope.isdown = false;
                //鼠标按下
                $scope.mousedown = function(e){
                    $scope.isdown = true;
                }
                //鼠标抬起
                $scope.mouseup = function(e){
                    $scope.isdown = false;
                }
                //鼠标进入
                $scope.mouseenter = function(e){
                    if($scope.isdown){
                        console.log(e.target.style.backgroundColor = "red");
                    }
                }
            });
        </script>
    </body>
    </html>
    弃用 ng-style

    个人小站欢迎来踩:驾校教练评价平台 | 为爱豆砌照片墙

  • 相关阅读:
    dir for RequestHandler and request
    python globals和locals
    Spring AOP(通知、连接点、切点、切面)
    Elasticsearch和Head插件安装(转)
    服务发现
    全面的软件测试( 转)
    软件开发项目人员配置
    阿里云oss缩略图如何产生读取 超简单 不看后悔(转)
    Elasticsearch模糊查询
    小米Pro 安装苹果系统
  • 原文地址:https://www.cnblogs.com/jying/p/5633203.html
Copyright © 2011-2022 走看看