确定在滚动条显示之前屏幕上有多少表行可见

时间:2018-08-07 07:57:24

标签: javascript html css reactjs twitter-bootstrap

背景:我正在使用一个仪表板,该仪表板下面显示一个标题和一个表格。该表可以有很多行(超过100行)。

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

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

使用的技术:React JS,Bootstrap表

对于轮播部分,我发现Bootstrap Carousel可以正常工作,但问题是要弄清楚屏幕上可见多少行。如何确定在滚动条出现之前可以在屏幕上显示多少行?非常感谢你!

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是:

  1. 在DOM中创建一个元素,该元素的高度将为100%(其他任何可能的高度也将起作用)。例如:

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

  2. 获取元素的高度。

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

  3. 知道单行占用了多少高度,只需将availableHeight除以,就可以知道要渲染多少行。如果您的行高是30:

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

答案 1 :(得分:0)

这是一个示例,您可以在整个div之前填充它。如果有人对此感兴趣,也可以做出jQuery答案。

我做了2格。一个具有设定高度的示例(在示例中为100%,但也可以为静态高度),并且在一个随内容而增长的可增长div中。

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

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

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

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>

答案 2 :(得分:0)

我知道您标记了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);