[英]Large list rendering in JavaScript
I am trying to render the list based on virtual rendering concept. 我试图基于虚拟渲染概念渲染列表。 I am facing some minor issues, but they are not blocking the behaviour. 我面临一些小问题,但他们并没有阻止这种行为。 Here is the working fiddle http://jsfiddle.net/53N36/9/ and Here are my problems 这是工作小提琴http://jsfiddle.net/53N36/9/ ,这是我的问题
I have tested it with 700000 items and 70 items in chrome. 我用700000件物品和70件镀铬物品进行了测试。 Below is the code 下面是代码
(function () {
var list = (function () {
var temp = [];
for (var i = 0, l = 70; i < l; i++) {
temp.push("list-item-" + (i + 1));
}
return temp;
}());
function listItem(text, id) {
var _div = document.createElement('div');
_div.innerHTML = text;
_div.className = "listItem";
_div.id = id;
return _div;
}
var listHold = document.getElementById('listHolder'),
ht = listHold.clientHeight,
wt = listHold.clientWidth,
ele = listItem(list[0], 'item0'),
frag = document.createDocumentFragment();
listHold.appendChild(ele);
var ht_ele = ele.clientHeight,
filled = ht_ele,
filledIn = [0];
for (var i = 1, l = list.length; i < l; i++) {
if (filled + ht_ele < ht) {
filled += ht_ele;
ele = listItem(list[i], 'item' + i);
frag.appendChild(ele);
} else {
filledIn.push(i);
break;
}
}
listHold.appendChild(frag.cloneNode(true));
var elements = document.querySelectorAll('#listHolder .listItem');
function MouseWheelHandler(e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
console.log(delta);
//if(filledIn[0] != 0 && filledIn[0] != list.length){
if (delta == -1) {
var start = filledIn[0] + 1,
end = filledIn[1] + 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = filledIn[0]; i < filledIn[1]; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
} else {
var start = filledIn[0] - 1,
end = filledIn[1] - 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = start; i < end; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
}
//}
}
if (listHold.addEventListener) {
listHold.addEventListener("mousewheel", MouseWheelHandler, false);
listHold.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
} else listHold.attachEvent("onmousewheel", MouseWheelHandler);
}());
Please suggest me on this. 请建议我这个。
EDIT: I have tried again and I am able to fix the indexing issue. 编辑:我再次尝试,我能够解决索引问题。 http://jsfiddle.net/53N36/26/ But how can I calculate the scroll position based on the array list currently displayed. http://jsfiddle.net/53N36/26/但是如何根据当前显示的数组列表计算滚动位置。
Is this the best method or any other?
I think something that would make this much easier is not to try to handle scrolling yourself. 我认为让这更容易的事情就是不要试图自己处理滚动。
In this fiddle I show that you can let the browser handle scrolling for you, even though we are using virtual rendering
. 在这个小提琴中,我表明你可以让浏览器为你处理滚动,即使我们正在使用virtual rendering
。
Using .scrollTop
I detect where the browser thinks the user is looking, and I draw in items based on that. 使用.scrollTop
我检测浏览器认为用户正在查看的位置,并根据该项绘制项目。
You'll note that if you set hidescrollbar
to false and the user uses it to scroll, my method still runs fine. 你会注意到,如果你将hidescrollbar
设置为false并且用户使用它来滚动,我的方法仍然运行良好。
Therefore, to calculate scroll position
you can just use .scrollTop
. 因此,要calculate scroll position
您只需使用.scrollTop
。
And as for custom scrolling, just make sure you influence the .scrollTop
of #listHolder
and recall refreshWindow()
至于自定义滚动,只需确保影响.scrollTop
的#listHolder
并调用refreshWindow()
CODE FROM FIDDLE 来自FIDDLE的代码
(function () {
//CHANGE THESE IF YOU WANT
var hidescrollbar = false;
var numberofitems = 700000;
//
var holder = document.getElementById('listHolder');
var view = null;
//get the height of a single item
var itemHeight = (function() {
//generate a fake item
var div = document.createElement('div');
div.className = 'listItem';
div.innerHTML = 'testing height';
holder.appendChild(div);
//get its height and remove it
var output = div.offsetHeight;
holder.removeChild(div);
return output;
})();
//faster to instantiate empty-celled array
var items = Array(numberofitems);
//fill it in with data
for (var index = 0; index < items.length; ++index)
items[index] = 'item-' + index;
//displays a suitable number of items
function refreshWindow() {
//remove old view
if (view != null)
holder.removeChild(view);
//create new view
view = holder.appendChild(document.createElement('div'));
var firstItem = Math.floor(holder.scrollTop / itemHeight);
var lastItem = firstItem + Math.ceil(holder.offsetHeight / itemHeight) + 1;
if (lastItem + 1 >= items.length)
lastItem = items.length - 1;
//position view in users face
view.id = 'view';
view.style.top = (firstItem * itemHeight) + 'px';
var div;
//add the items
for (var index = firstItem; index <= lastItem; ++index) {
div = document.createElement('div');
div.innerHTML = items[index];
div.className = "listItem";
view.appendChild(div);
}
console.log('viewing items ' + firstItem + ' to ' + lastItem);
}
refreshWindow();
document.getElementById('heightForcer').style.height = (items.length * itemHeight) + 'px';
if (hidescrollbar) {
//work around for non-chrome browsers, hides the scrollbar
holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
}
function delayingHandler() {
//wait for the scroll to finish
setTimeout(refreshWindow, 10);
}
if (holder.addEventListener)
holder.addEventListener("scroll", delayingHandler, false);
else
holder.attachEvent("onscroll", delayingHandler);
}());
<div id="listHolder">
<div id="heightForcer"></div>
</div>
html, body {
width:100%;
height:100%;
padding:0;
margin:0
}
body{
overflow:hidden;
}
.listItem {
border:1px solid gray;
padding:0 5px;
width: margin : 1px 0px;
}
#listHolder {
position:relative;
height:100%;
width:100%;
background-color:#CCC;
box-sizing:border-box;
overflow:auto;
}
/*chrome only
#listHolder::-webkit-scrollbar{
display:none;
}*/
#view{
position:absolute;
width:100%;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.