确定滚动条显示之前屏幕上可见的表行数



背景:我正在开发一个面板,它在下面显示一个标题和一个表。该表可以有许多行(超过100行(。

问题:大量的行会触发一个垂直滚动条显示,从而隐藏其余的行。

可能的解决方案:我想旋转,仪表板所在的每个屏幕上都显示哪些表行。我想避免设置屏幕上可见的固定行数,而是在滚动条显示之前确定屏幕上可以放多少行。这意味着,首先,我想确定在滚动条出现之前,屏幕上有多少行是可见的,然后创建一个旋转木马动画,在那里显示下一个X行,直到所有行都显示出来,动画重置。

使用的技术:React JS,引导表

对于旋转木马部分,我发现Bootstrap旋转木马运行良好,但问题是弄清楚屏幕上有多少行可见。在滚动条出现之前,我如何确定屏幕上可以显示多少行?非常感谢!

一种可能的解决方案是:

  1. 在DOM中创建一个100%高度的元素(任何其他可能的高度也可以(。例如:

    <div id="row-wrapper" style="height: 100%"></div>

  2. 获取元素的高度。

    var availableHeight = document.getElementById('row-wrapper').clientHeight;

  3. 知道单行占据的高度只需除以可用高度,就可以知道要渲染的行数。如果您的行高为30:

var numberOfRows = Math.floor(availableHeight / 30);

我知道您标记了ReactJS,但一个好的基础是始终保持您的DOM尽可能小。我的策略是将数据保存在JavaScript中,只向DOM介绍绝对需要的内容。

下面是一个简单的例子,显示了带有偏移的10行:

var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100000) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.value = "0";
var table = document.body.appendChild(document.createElement("table"));
table.style.width = "100%";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
function update() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
}
}
offsetInput.addEventListener("change", update);
offsetInput.addEventListener("keyup", update);

从这里开始,这将是一个CSS技巧和读取滚动条以获得偏移量的问题。

var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.max = "" + (dummyData.length - pagesize);
offsetInput.value = "0";
var outerContainer = document.body.appendChild(document.createElement("div"));
outerContainer.style.maxHeight = "400px";
outerContainer.style.width = "450px";
outerContainer.style.overflowY = "scroll";
var innerContainer = outerContainer.appendChild(document.createElement("div"));
innerContainer.style.height = dummyData.length * 20 + 200 + "px";
var table = innerContainer.appendChild(document.createElement("table"));
table.style.position = "absolute";
table.style.width = "400px";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
var handle;
function update() {
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
clearTimeout(handle);
handle = setTimeout(function() {
offsetInput.value = offset.toString();
outerContainer.scrollTop = offset * 20;
}, 100);
}
function updateInput() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
}
update();
}
function updateScroll() {
offset = Math.floor(outerContainer.scrollTop / 20);
update();
}
outerContainer.addEventListener("scroll", updateScroll);
offsetInput.addEventListener("change", updateInput);
offsetInput.addEventListener("keyup", updateInput);

这是一个如何填充div直到其填满的示例。如果有人对此感兴趣,也做了一个jQuery答案。

我做了两个div。一个具有设置的高度(在示例中为100%,但也可以是静态高度(,并且位于随内容增长的可增长div内。

首先,它将填充可增长的div,只要它小于内容div。最后添加的元素可能比剩余空间更大。如果发生这种情况,它将删除最后一个元素。

这也适用于具有动态高度的内容。

注意:当使用while循环时,最好有一个备份计划来避免无限循环。因此,我添加了一个最大记录变量。

Javascript:

window.onload = function() {
document.getElementById('fill').onclick = function() {
var content = document.getElementById('content');
var growableWrapper = document.getElementById('growableWrapper');
var maxRecords = 50;
while ((content.childNodes.length === 0 || parseInt(window.getComputedStyle(growableWrapper).height) < parseInt(window.getComputedStyle(content).height)) && growableWrapper.childNodes.length < maxRecords) {
var newElement = document.createElement("p");
var newText = document.createTextNode("Test");
newElement.appendChild(newText);
growableWrapper.appendChild(newElement);
}
if (window.getComputedStyle(growableWrapper).height > window.getComputedStyle(content).height && growableWrapper.childNodes.length > 1) {
growableWrapper.removeChild(growableWrapper.childNodes[growableWrapper.childNodes.length - 1]);
}
}
}
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill,
#content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>

jQuery:

$(document).ready(function() {
$('#fill').on('click', function() {
var content = $('#content');
var growableWrapper = $('#growableWrapper');
var maxRecords = 50;
while ((content.children().length === 0 || growableWrapper.height() < content.height()) && growableWrapper.children().length < maxRecords) {
growableWrapper.append('<p>test</p>');
}
if(growableWrapper.height() > content.height() && growableWrapper.children().length > 1) {
growableWrapper.children().last().remove();
}
});
});
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill, #content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>

最新更新