Fon*_*hau 21 javascript css html-table
我正在开发一个用于产品数据管理的webapp,其中产品数据显示在一个包含4列(索引号,SKU,产品描述和库存)的表中.
我面临的问题是,当表变得非常大(> 1000行)时,页面非常滞后,特别是当我将鼠标悬停在一行上时(我__CODE__
在CSS中定义).
我尝试通过使用一些javascript来部分地显示数据并在用户向下滚动时加载更多来解决此问题:
/**
* @namespace Start the project called 'stck'
*/
var stck = {};
/**
* Variable to save stock loaded
*/
stck.stockInfo = [];
/**
* Load the item informaction acording the SKU
* @private
* @param {string} SKU The SKU of the item
*/
stck.loadItemInformation = function(SKU) {
var descriptionsTable = document.getElementById('descriptionsTable');
for (var rowsLength = descriptionsTable.rows.length - 1; --rowsLength; ) {
descriptionsTable.deleteRow(1);
}
var pricesTable = document.getElementById('pricesTable');
for (var rowsLength = pricesTable.rows.length - 1; --rowsLength; ) {
pricesTable.deleteRow(1);
}
document.getElementById('tableHeader').style.cssText = '';
document.getElementById('tableContent').style.cssText = '';
// Load data with AJAX and process here
document.getElementById('addItemButton').className = 'hidden';
document.getElementById('saveButton').className = document.getElementById('cancelButton').className = '';
document.getElementById('tables').className = 'hidden';
document.getElementById('editItem').className = 'active';
};
/**
* Show row to the 'tableContent' table.
* @public
* @param {number} showQuantity The quantity that will be loaded
* @param {boolean} isLoadNewStock Define if the quantity that are going to be show are lower than stock, will load new stock information or not
*/
stck.showRow = function(showQuantity, isLoadNewStock) {
var stock = stck.stockInfo;
var tableContent = document.getElementById('tableContent');
var tableContentRowsLength = tableContent.rows.length;
var stockInfoLength = stck.stockInfo.length;
var toIndex = tableContentRowsLength + showQuantity;
if (toIndex > stockInfoLength) {
if (isLoadNewStock && stck.loadStock(10, true, false)) {
return;
} else {
toIndex = stockInfoLength;
}
}
for (var i = tableContentRowsLength, row, rowNumber, cellIndex, SKUCell, descriptionCell, stockCell, clickHandler; i < toIndex; ++i) {
row = tableContent.insertRow(i);
rowNumber = document.createElement('TH');
rowNumber.innerText = i + 1;
row.appendChild(rowNumber);
cellIndex = 0;
SKUCell = row.insertCell(++cellIndex);
SKUCell.innerHTML = stock[i][0];
descriptionCell = row.insertCell(++cellIndex);
descriptionCell.innerHTML = stock[i][1];
stockCell = row.insertCell(++cellIndex);
stockCell.className = 'stock';
stockCell.innerHTML = stock[i][2];
clickHandler = function(row) {
return function() {
stck.loadItemInformation(stock[row][0]);
};
};
row.onclick = clickHandler(i);
}
};
/**
* This code is for test
*/
for (var i = 0; i < 10000; ++i) {
stck.stockInfo.push(['TESTSKU', 'A test item', i]);
}
stck.showRow(10000, false)
Run Code Online (Sandbox Code Playgroud)
它给出了一个很好的结果,但是这可以防止按下到达最后一行End,并且当加载大量行时,页面再次出现滞后.
这个问题有解决方案吗?
编辑:与表相关的CSS代码.
html{height:100%;background-color:#FFF;background:-webkit-gradient(linear,left top,left bottom,from(#EEE),to(#FFF));background:-webkit-radial-gradient(#FFF,#FFF 35%,#EEE);background:-moz-radial-gradient(#FFF,#FFF 35%,#EEE);background:radial-gradient(#FFF,#FFF 35%,#EEE);-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:-moz-none;-o-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-webkit-font-smoothing:antialiased;cursor:default}
::-moz-selection,::selection{background:transparent}
::-moz-focus-inner{border:none}
body{margin:0;background-color:transparent;overflow:hidden}
body,th,td,input,textarea{color:#333;font:13px/1.2 Arial,Helvetica,sans-serif;-webkit-border-radius:0;text-rendering:optimizelegibility}
a{outline:none}
img{border:none;behavior:url(/i/iepngfix.htc)}
table{border-spacing:0;border-collapse:collapse}
article,aside,hgroup,footer,header,nav,section{display:block}
input,select{margin:2px 0;padding:3px;-webkit-border-radius:0;-webkit-box-shadow:none;-webkit-appearance:none;border:1px solid #B8ADA5;overflow:visible}
input[type="number"]::-webkit-outer-spin-button{display:none}
input:hover,select:hover{border-color:#4A0}
input:focus,select:focus{border-color:#4A0;-webkit-box-shadow:0 0 3px #4A0;-moz-box-shadow:0 0 3px #4A0;box-shadow:0 0 3px #4A0;outline:none}
input::-moz-focus-inner{border:0;padding:0}
.b{clear:both;margin-top:10px;padding:0 4px;border-top:1px dashed #CCC;text-align:right}
.b input{width:auto;min-width:54px;height:29px;margin:6px 0 6px 6px;padding:0 8px;border:1px solid #3079ED;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background-color:#4D90FE;background-image:-webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#4787ED));background-image:-moz-linear-gradient(top,#4D90FE,#4787ED);background-image:-o-linear-gradient(top,#4D90FE,#4787ED);background-image:linear-gradient(top,#4D90FE,#4787ED);color:#FFF;font-weight:700;text-decoration:none;line-height:27px;-webkit-transition:0.1s ease-in-out;-moz-transition:0.1s ease-in-out;-o-transition:0.1s ease-in-out;transition:0.1s ease-in-out;text-align:center;cursor:pointer}
.b input:hover{background-color:#357AE8;background-image:-webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#357AE8));background-image:-moz-linear-gradient(top,#4D90FE,#357AE8);background-image:-o-linear-gradient(top,#4D90FE,#357AE8);background-image:linear-gradient(top,#4D90FE,#357AE8)}
.b input:active,.b input:focus{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.3);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.3);box-shadow:inset 0 1px 2px rgba(0,0,0,.3);outline:none}
input:disabled,textarea:disabled{color:#999;cursor:not-allowed}
textarea:disabled::-webkit-input-placeholder{color:#F9F9F9}
.b input:disabled{color:#EEE;cursor:not-allowed}
.b input:disabled:hover{background-color:#4D90FE;background-image:-webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#4787ED));background-image:-moz-linear-gradient(top,#4D90FE,#4787ED);background-image:-o-linear-gradient(top,#4D90FE,#4787ED);background-image:linear-gradient(top,#4D90FE,#4787ED);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}
#gpanel{position:fixed;top:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:43px;padding:0 5px;-moz-border-radius:0 1px;border-bottom:1px solid #000;background-color:rgba(0,0,0,.85);line-height:46px;-webkit-transition:.1s ease-in-out;-moz-transition:.1s ease-in-out;-o-transition:0.1s ease-in-out;transition:.1s ease-in-out;overflow:hidden;z-index:10}
#gpanel.hidden{top:-44px}
#gpanel ul{list-style:none;margin:0;padding:0}
#gpanel li{float:left;overflow:hidden}
#gpanel a{display:block;padding:0 10px;color:#DDD;font-weight:700;text-decoration:none;white-space:nowrap;cursor:pointer;-webkit-transition:.1s ease-in-out;-moz-transition:.1s ease-in-out;-o-transition:0.1s ease-in-out;transition:.1s ease-in-out}
#gpanel a:hover{background-color:rgba(204,204,204,.4);color:#FFF}
@-webkit-keyframes loading {
0% {background-color:rgba(204,204,204,.4)}
50% {background-color:rgba(119,187,68,.9)}
100% {background-color:rgba(204,204,204,.4)}
}
@-moz-keyframes loading {
0% {background-color:rgba(204,204,204,.4)}
50% {background-color:rgba(119,187,68,.9)}
100% {background-color:rgba(204,204,204,.4)}
}
#gpanel a:active,#gpanel a:focus{background-color:rgba(119,187,68,.9);-webkit-animation:loading .5s infinite linear;-moz-animation:loading .5s infinite linear}
#gnav{float:left;overflow:hidden}
#gmanager{float:right;margin-right:4px}
#body{margin-top:44px;overflow:auto}
#overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(127,127,127,0.5);background:-webkit-radial-gradient(rgba(127,127,127,.5),rgba(127,127,127,.5) 35%,rgba(0,0,0,.7));background:-moz-radial-gradient(rgba(127,127,127,.5),rgba(127,127,127,.5) 35%,rgba(0,0,0,.7));-webkit-transition:opacity .25s linear;-moz-transition:opacity .25s linear;transition:opacity .25s linear;opacity:1;overflow-y:auto;z-index:15}
#overlay.hidden{opacity:0;visibility:hidden}
#overlay .hidden{display:none}
#overlay form{position:absolute;top:50%;left:50%;border:1px solid #BCC1D0;-webkit-border-radius:2px;-moz-border-radius:2px;-webkit-box-shadow:0px 5px 80px #505050;-moz-box-shadow:0px 5px 80px #505050;background:#FFF url(../image/lightbox.png) bottom repeat-x;text-align:left}.window p{margin:5px 0}.window label{display:block;text-transform:uppercase;font:700 10px Tahoma,Geneva,sans-serif;zoom:1}.window input[type="text"],.window input[type="number"],.window input[type="password"],.window textarea{padding:2px;border:1px solid;border-color:#999 #333 #333 #999;background:#FFF}.window table{margin:0;border-spacing:0;border-collapse:collapse}.window th,.window td{border:none;border-bottom:1px solid #CCC;background:none}.window select{width:65px}#code,#desc,#desc_cn,#password,#largedescription{width:350px}#price{width:100px}.window input[type="submit"]{padding:5px 10px;border:1px solid;border-color:#FC0 #F60 #F60 #FC0;background:#F90}.window input[type="reset"]{padding:5px 10px;border:1px solid;border-color:#EEE #333 #333 #EEE;background:#CCC}
#overlay h1,#body h1{margin:0;padding:10px 20px 5px;border-bottom:1px solid #CCC;color:#848589;font:400 30px 'Segoe UI',Arial,Helvetica,sans-serif}
#overlay h1{font-size:24px}
#overlay .contentArea{padding:10px 15px 5px}
#overlay label{font-weight:700}
form#addItemPage{width:500px;margin:-126px 0 0 -251px}
#addItemPage .contentArea p{overflow:auto}
#addItemPage .contentArea label{display:block;width:470px;line-height:28px}
#addItemPage .contentArea input{float:right;width:330px;margin-right:3px}
#body h1{height:41px}
#stock a{color:#FFF;background-color:#7B4}
#functions{padding:13px 10px;float:right}
#functions ul{list-style:none;margin:0;padding:0}
#functions li{display:inline-block;min-width:54px;height:27px;margin-left:6px;padding:0 8px;border:1px solid #3079ED;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#4D90FE;background-image:-webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#4787ED));background-image:-moz-linear-gradient(top,#4D90FE,#4787ED);background-image:-o-linear-gradient(top,#4D90FE,#4787ED);background-image:linear-gradient(top,#4D90FE,#4787ED);color:#FFF;font-weight:700;text-decoration:none;line-height:27px;cursor:pointer}
#functions li:hover{background:#357AE8;background-image:-webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#357AE8));background-image:-moz-linear-gradient(top,#4D90FE,#357AE8);background-image:-o-linear-gradient(top,#4D90FE,#357AE8);background-image:linear-gradient(top,#4D90FE,#357AE8)}
#functions li:active,#functions li:focus{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.3);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.3);box-shadow:inset 0 1px 2px rgba(0,0,0,.3);outline:none}
#functions li.hidden{display:none}
#tables{position:absolute;top:101px;bottom:0;width:100%;-webkit-transition:.3s linear;-moz-transition:.3s linear;transition:.3s linear;overflow-y:scroll}
#tables.hidden{opacity:0;-webkit-transform:scale(0);-moz-transform:scale(0);-o-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}
#tables:focus{outline:none}
::-moz-focus-inner{border:none}
#tables table{width:100%;border-collapse:collapse;border-spacing:0;table-layout:fixed;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
#tableHeader{top:101px}
.indexCol{width:50px}
.SKUCol{width:115px}
.brandCol{width:105px}
.stockCol{width:85px}
tr#noItem{text-align:center;cursor:default}
tr#noItem:hover{background:#FFF}
.stock{text-align:right}
#tables th,#tables td{padding:9px 6px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}
#tables thead th{border-bottom:1px solid #CCC;background-color:#F5F5F5;background-image:-webkit-gradient(linear,left top,left bottom,from(#F5F5F5),to(#F1F1F1));background-image:-moz-linear-gradient(top,#F5F5F5,#F1F1F1);background-image:-o-linear-gradient(top,#F5F5F5,#F1F1F1);background-image:linear-gradient(top,#F5F5F5,#F1F1F1);font-weight:700;cursor:default}
#tables tbody th{font-weight:700;text-overflow:none}
#tables tbody tr{background:#FFF;cursor:pointer}
#tables tbody tr:nth-child(even){background:#F8F9FC}
#tables tbody tr:hover{background:#CDE}
#editItem{position:fixed;top:101px;bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;padding:0 20px;visibility:hidden;opacity:0;-webkit-transform:scale(2);-moz-transform:scale(2);-o-transform:scale(2);-ms-transform:scale(2);transform:scale(2);-webkit-transition:.3s linear;-moz-transition:.3s linear;-o-transition:.3s linear;transition:.3s linear}
#editItem.active{visibility:visible;opacity:1;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
#editItem header{height:51px;overflow:auto}
#editItem h2{float:left;margin:0 20px 0 0;padding:10px 0;color:#7B4;font:400 20px 'Seoge UI',Arial,Helvetica,sans-serif}
#editItem ul{list-style:none;margin:10px 0;padding:0;border-bottom:1px solid #7B4}
#editItem li{display:inline-block;margin:0 5px;padding:8px 10px 7px;color:#7B4;cursor:pointer;text-transform:uppercase;-webkit-transition:.15s linear;-moz-transition:.15s linear;transition:.15s linear}
#editItem li:hover{background:rgba(204,204,204,.4);color:#000}
#editItem li.active{background-color:#7B4;color:#FFF;font-weight:700;cursor:default}
#editItem .container{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:100%;overflow:hidden}
#editItem .tabs{position:relative;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;height:100%;-webkit-transition:.5s ease-in-out;-moz-transition:.5s ease-in-out;-o-transition:.5s ease-in-out;transition:.5s ease-in-out}
#editItem section{width:100%;height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;overflow-y:auto}
#editItem section div{float:left;width:50%;padding:5px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
#editItem label{float:left;width:20%;min-width:50px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
#editItem table{width:100%;table-layout:fixed}
#descriptionsTable{margin-top:5px;border-top:1px solid #DDD}
#editItem th{font-weight:700;text-align:left}
#editItem th, #editItem td{padding:5px 2px}
#editItem img{display:block;margin:0 auto;opacity:.5;cursor:pointer}
#editItem tr:hover img{opacity:1}
#inputsTable .labelCol{width:100px}
#inputsTable label{float:none;display:block;width:100%;height:100%}
#editItem input, #editItem select{width:100%;height:26px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
#editItem .languageCol{width:190px}
#editItem .deleteCol{width:25px}
#editItem #statusInput{width:auto;height:auto;margin:4px 4px 4px 0;-webkit-appearance:checkbox}
#editItem label[for="statusInput"]{display:inline;width:auto;height:auto}
#editItem textarea{box-sizing:border-box;width:100%}
#newDescriptionRow select{visibility:hidden}
Run Code Online (Sandbox Code Playgroud)
EDIT2:演示.
Thi*_*iff 20
减慢循环的第一件事是.insertRow()
.你是在你的循环顶部做这个,然后添加单元格.添加行后,在添加每个单元格后,浏览器正在进行布局计算.而是使用.createElement()
然后.appendChild()
在循环结束时.
演示:http://jsfiddle.net/ThinkingStiff/gyaGk/
更换:
row = tableContent.insertRow(i);
Run Code Online (Sandbox Code Playgroud)
附:
row = document.createElement('tr');
Run Code Online (Sandbox Code Playgroud)
并在循环结束时添加:
tableContent.tBodies[0].appendChild(row);
Run Code Online (Sandbox Code Playgroud)
这将解决您的加载速度问题.至于悬停,你有太多的CSS规则使用标签选择器影响你的tr
和td
元素.我删除了一些,并在几个上使用了类,并且悬停突出显示更快.具体而言,我注意到,overflow: hidden
在td
元素慢了显着.考虑组合一些规则,使用更简单的选择器,并向元素添加类以便更快地进行CSS处理.在悬停期间,布局引擎必须重新计算许多内容,CSS规则越少越好.我在你的代码中看到的一个例子#tables tbody tr
是tbody
表中只有一个.#tables tr
本来就足够了.比其中任何一个都更好.我.row
在我的演示中使用过.
Google Page Speed的最佳做法:
table tbody tr td
body section article
(body
不需要的)body *
ul li
ul > li > a
form#UserLogin
(#
已经是特定的)如果您的表具有常规列(没有 colspan 和/或 rowspan),您可以稍微改进应用该table-layout:fixed
属性的渲染时间:
MDN:https : //developer.mozilla.org/en/CSS/table-layout
在“固定”布局方法下,一旦下载并分析了第一个表格行,就可以呈现整个表格。这可以加快“自动”布局方法的渲染时间,但随后的单元格内容可能不适合提供的列宽。
如果您正在使用非常大的表(例如 5000 甚至 500,000 行),我推荐一个名为Clusterize的小插件。您甚至不需要 jQuery 来使用它。这个想法类似于延迟加载图像,并且在实践中效果非常好。