本文地址:http://www.cnblogs.com/jying/p/5633203.html javascript
熟悉 angular 的前端對ng-style 必定不陌生,這個傢伙能夠綁定一個函數,使得咱們能夠在函數中根據不一樣的參數返回不一樣的樣式,以下是一個簡單的實例:html
<!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>
在該實例中,咱們經過 $index 綁定不一樣的文字顏色,是否是感受很方便呢,程序猿和代碼其樂融融,相處的很好嘛O(∩_∩)O前端
直到有一天......業務提出這麼一個需求:在成千上萬的 span 上拖動鼠標選擇區域設置背景色!java
拖動鼠標嘛,簡單!咱們有 ng-mouseenter、ng-mouseleave、ng-mousemove、ng-mouseup 、ng-mousedown!挽起袖子搞起! app
<!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-style 是在何時綁定控件的 style 樣式呢?因而給$scope.setStyle 添加輸出:console.log(idx); 結果剛纔較流暢的界面卡出翔了 ←.← ide
好吧,咱們把數字改小點看看效果 ↓ . ↓函數
<!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>
按下 F12 查看控制檯 ,鼠標移入數字區,能夠看到console.log 不停的輸出,也就是說此時 ng-style 是不停的重複綁定的,這顯然是耗費資源的,在某些實時要求高的界面就會致使卡頓現象,爲了不這種重複的資料消耗決定換個方式綁定style,且要只綁定一次,想來想去決定仍是用 for 遍歷控件綁定post
$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 的使用了。url
所有實現代碼以下:
<!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>