我構建了一個基本網格,其中標題和內容是分開的。這樣做是為了使將來能夠擴展到更復雜的表格可視化。滾動內容時,標題是同步的。
我面臨的挑戰是滾動滯后。我已經實作了一個節流閥,但它的性能仍然很差(注意我只是在做一個基本的 scrollLeft 同步,沒什么特別的)。它嘗試了各種范圍,從 0 毫秒到 30 毫秒,但沒有實質性改進。
然后我查看了渲染性能,打開開發者工具查看頁面的哪些部分被重繪,并且也僅限于滾動條和頁眉被重繪。(mp4 視頻https://filedropper.com/d/s/GxsNi1nG4URwQ25uNUSCU5606HKNF0)
我還嘗試查看 css,消除 table-layout:fixed 并沒有任何區別,而且在這里我沒有做一些真正影響渲染的不尋常的事情。
我懷疑某些特定的周圍布局/彈性布局會嚴重影響渲染性能。還有另一種方法可以真正查明延遲的來源嗎?公平地說,在 StackOverflow 上運行此處的代碼段也會顯示滯后。
function Grid(parentNode){
this.ready = false;
this.parentNode = typeof parentNode === 'string' ? document.getElementById(parentNode) : parentNode;
if (!this.parentNode) {
console.error('Exception - Grid','Cannot find parentnode');
return;
}
// quick n dirty references (normally created when rendering the grid)
this.gridContent = this.parentNode.querySelector(".gridcontent");
this.gridHeaderContent = this.parentNode.querySelector(".gridheadercontent");
this.gridHeaderWrapper = this.parentNode.querySelector(".gridheaderwrapper");
this.Init();
}
Grid.prototype = {
Init: function() {
//this.gridContent.addEventListener('scroll',this.Scroll.bind(this));
this.gridContent.addEventListener('scroll', Throttle(30, this.Scroll.bind(this)));
},
Scroll: function () {
let scrollbarWidth = this.GetScrollbarWidth();
let scrollLeft = event.srcElement.scrollLeft;
this.gridHeaderContent.scrollLeft = scrollLeft;
if (scrollbarWidth > 0) {
this.gridHeaderWrapper.style.paddingRight = scrollbarWidth 'px';
}
},
GetScrollbarWidth: function () {
return this.gridContent.offsetWidth - this.gridContent.clientWidth;
}
}
// manage the scroll event spam, resulting in too many redraws
function Throttle(ms, callback) {
let lastCall = 0;
return function () {
let now = new Date().getTime(),
diff = now - lastCall;
if (diff >= ms) {
lastCall = now;
callback.apply(this, arguments);
}
};
}
new Grid("grid");
.component.grid {
position: relative;
border-color: #dee2e6;
overflow: hidden;
height: 100%;
}
.component.grid .gridheaderwrapper {
overflow: hidden;
border: 1px solid lightgrey;
}
.component.grid .gridheaderwrapper .gridheadercontent {
overflow: hidden;
border-right: 1px solid lightgrey;
}
.component.grid .gridheaderwrapper .gridheadercontent .gridheadertable {
border-collapse: collapse;
table-layout: fixed;
}
.component.grid .gridcontentwrapper {
overflow: hidden;
vertical-align: middle;
background-color: #fff;
height: 50%;
}
.component.grid .gridcontentwrapper .gridcontent {
position: relative;
overflow: auto;
height: 100%;
}
.component.grid .gridcontentwrapper .gridcontent .gridcontenttable {
border-collapse: collapse;
table-layout: fixed;
}
.component.grid th {
text-align: left;
white-space: nowrap;
padding: 10px 8px;
}
.component.grid th[rowspan] {
vertical-align: bottom;
}
.component.grid td {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: 10px 8px;
}
<div id="grid" style="padding: 10px;">
<div class="component grid" id="51177476-273f-4277-954c-dd7e576c5c9d">
<div class="gridheaderwrapper">
<div class="gridheadercontent">
<table class="gridheadertable" style="width: 1177px;">
<colgroup>
<col style="width: 55px;" />
<col style="width: 113px;" />
<col style="width: 80px;" />
<col style="width: 95px;" />
<col style="width: 93px;" />
<col style="width: 136px;" />
<col style="width: 61px;" />
<col style="width: 292px;" />
<col style="width: 88px;" />
<col style="width: 89px;" />
<col style="width: 75px;" />
</colgroup>
<thead>
<tr>
<th>
<p>
<label><input type="checkbox" class="filled-in" /><span> </span></label>
</p>
</th>
<th>Name</th>
<th>DataType</th>
<th>PrimaryKey</th>
<th>ForeignKey</th>
<th>DataAnalysisType</th>
<th>Visible</th>
<th>Id</th>
<th>Created</th>
<th>Modified</th>
<th>Selected</th>
</tr>
</thead>
</table>
</div>
</div>
<div class="gridcontentwrapper">
<div class="gridcontent">
<table class="gridcontenttable" style="width: 1177px;">
<colgroup>
<col style="width: 55px;" />
<col style="width: 113px;" />
<col style="width: 80px;" />
<col style="width: 95px;" />
<col style="width: 93px;" />
<col style="width: 136px;" />
<col style="width: 61px;" />
<col style="width: 292px;" />
<col style="width: 88px;" />
<col style="width: 89px;" />
<col style="width: 75px;" />
</colgroup>
<tbody>
<tr id="daa93d55-bdd5-4a20-9bef-2567efe75971">
<td>
<p>
<label><input type="checkbox" class="filled-in" /><span> </span></label>
</p>
</td>
<td>CategoryID</td>
<td>int</td>
<td>true</td>
<td>false</td>
<td>2</td>
<td>true</td>
<td>daa93d55-bdd5-4a20-9bef-2567efe75971</td>
<td>01/01/0001</td>
<td>01/01/0001</td>
<td>false</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
uj5u.com熱心網友回復:
- 將油門閾值降低到一個較小的數字(例如 5)。
- 如果您在滾動時仍然填充滯后,請嘗試使用
transform替換scrollLeft,并添加will-change到提示瀏覽器如何更改元素。
function Grid(parentNode){
this.ready = false;
this.parentNode = typeof parentNode === 'string' ? document.getElementById(parentNode) : parentNode;
if (!this.parentNode) {
console.error('Exception - Grid','Cannot find parentnode');
return;
}
// quick n dirty references (normally created when rendering the grid)
this.gridContent = this.parentNode.querySelector(".gridcontent");
this.gridHeaderContent = this.parentNode.querySelector(".gridheadercontent");
this.gridHeaderWrapper = this.parentNode.querySelector(".gridheaderwrapper");
this.gridTable = this.parentNode.querySelector(".gridheadertable");
this.Init();
}
Grid.prototype = {
Init: function() {
//this.gridContent.addEventListener('scroll',this.Scroll.bind(this));
this.gridContent.addEventListener('scroll', Throttle(5, this.Scroll.bind(this)));
},
Scroll: function () {
let scrollbarWidth = this.GetScrollbarWidth();
let scrollLeft = event.srcElement.scrollLeft;
this.gridTable.style.transform = `translateX(-${scrollLeft}px)`;
},
GetScrollbarWidth: function () {
return this.gridContent.offsetWidth - this.gridContent.clientWidth;
}
}
// manage the scroll event spam, resulting in too many redraws
function Throttle(ms, callback) {
let lastCall = 0;
return function () {
let now = new Date().getTime(),
diff = now - lastCall;
if (diff >= ms) {
lastCall = now;
callback.apply(this, arguments);
}
};
}
new Grid("grid");
.component.grid {
position: relative;
border-color: #dee2e6;
overflow: hidden;
height: 100%;
}
.component.grid .gridheaderwrapper {
overflow: hidden;
border: 1px solid lightgrey;
}
.component.grid .gridheaderwrapper .gridheadercontent {
overflow: hidden;
border-right: 1px solid lightgrey;
}
.component.grid .gridheaderwrapper .gridheadercontent .gridheadertable {
border-collapse: collapse;
table-layout: fixed;
will-change: transform;
}
.component.grid .gridcontentwrapper {
overflow: hidden;
vertical-align: middle;
background-color: #fff;
height: 50%;
}
.component.grid .gridcontentwrapper .gridcontent {
position: relative;
overflow: auto;
height: 100%;
}
.component.grid .gridcontentwrapper .gridcontent .gridcontenttable {
border-collapse: collapse;
table-layout: fixed;
}
.component.grid th {
text-align: left;
white-space: nowrap;
padding: 10px 8px;
}
.component.grid th[rowspan] {
vertical-align: bottom;
}
.component.grid td {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: 10px 8px;
}
<div id="grid" style="padding: 10px;">
<div class="component grid" id="51177476-273f-4277-954c-dd7e576c5c9d">
<div class="gridheaderwrapper">
<div class="gridheadercontent">
<table class="gridheadertable" style="width: 1177px;">
<colgroup>
<col style="width: 55px;" />
<col style="width: 113px;" />
<col style="width: 80px;" />
<col style="width: 95px;" />
<col style="width: 93px;" />
<col style="width: 136px;" />
<col style="width: 61px;" />
<col style="width: 292px;" />
<col style="width: 88px;" />
<col style="width: 89px;" />
<col style="width: 75px;" />
</colgroup>
<thead>
<tr>
<th>
<p>
<label><input type="checkbox" class="filled-in" /><span> </span></label>
</p>
</th>
<th>Name</th>
<th>DataType</th>
<th>PrimaryKey</th>
<th>ForeignKey</th>
<th>DataAnalysisType</th>
<th>Visible</th>
<th>Id</th>
<th>Created</th>
<th>Modified</th>
<th>Selected</th>
</tr>
</thead>
</table>
</div>
</div>
<div class="gridcontentwrapper">
<div class="gridcontent">
<table class="gridcontenttable" style="width: 1177px;">
<colgroup>
<col style="width: 55px;" />
<col style="width: 113px;" />
<col style="width: 80px;" />
<col style="width: 95px;" />
<col style="width: 93px;" />
<col style="width: 136px;" />
<col style="width: 61px;" />
<col style="width: 292px;" />
<col style="width: 88px;" />
<col style="width: 89px;" />
<col style="width: 75px;" />
</colgroup>
<tbody>
<tr id="daa93d55-bdd5-4a20-9bef-2567efe75971">
<td>
<p>
<label><input type="checkbox" class="filled-in" /><span> </span></label>
</p>
</td>
<td>CategoryID</td>
<td>int</td>
<td>true</td>
<td>false</td>
<td>2</td>
<td>true</td>
<td>daa93d55-bdd5-4a20-9bef-2567efe75971</td>
<td>01/01/0001</td>
<td>01/01/0001</td>
<td>false</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/420793.html
標籤:
