【技术分享】用javascript处理十万条数据

王集鹄 2010-12-17 01:42:59
加精
这个标题只是为了吸引眼球

当前端开发人员面对成千上万条记录要显示的时候,我们该怎么处理?创建上千上万个Dom对象?

我的思路就是:把看到的区域当画布,创建足够能展现界面的Dom就够了。

比如一个屏幕的高度一般是1000像素左右,假设一条记录占用的高度是24像素,我们只用创建42个对象即可。

接下来就是对这42个对象进行数据填充,通过滚动条调整填充数据的起始下标。

示例:
http://csdntools.googlecode.com/svn/trunk/demo/biglist.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>大数据量显示 Demo</title>
<style type="text/css">
.panel{
overflow:scroll;
width:200px;
height:80%;
}
.panel .scroll{
}
.item{
width:500px;
height:20px;
}
.odd{
background-color:#ccc;
}
.items{
overflow:hidden;
position:absolute;
}
.red{
color:red;
}
.green{
color:green;
}
</style>
</head>
<body>
<div><input id="sort_index" type="button" value="按序号排"/><input id="sort_random" type="button" value="按随机值排"/></div>

<script>
window.console = window.console || { log: function() {} };

function absolutePoint(element) {
var result = [element.offsetLeft, element.offsetTop];
element = element.offsetParent;
while (element) {
result[0] += element.offsetLeft;
result[1] += element.offsetTop;
element = element.offsetParent;
}
return result;
}

/**
* 设计:王集鹄
* 日期:2010年12月17日
* 欢迎关注:http://t.sina.com.cn/zswang
*/
function ListView(options){
options = options || {};

var self = this,
$C = function(tagName) { return document.createElement(tagName); }, // 创建节点
p,
height,
item_height, // 项高
view_count, // 可见项条数
parent = options.parent || document.body, // 容器
height, // 面板历史高度
div_panel = $C("div"),
div_scroll = $C("div"),
div_items = $C("div"),
div_items_list = [$C("div")],
freed = [div_panel, div_scroll, div_items]; // 可释放的对象

div_panel.className = "panel";
parent.appendChild(div_panel);

div_items.className = "items";
document.body.appendChild(div_items);

div_scroll.className = "scroll";
div_panel.appendChild(div_scroll);

div_panel.onscroll = function() {
doChange();
}
div_panel.onresize = function() {
doChange();
}

div_items_list[0].className = "item";
div_items.appendChild(div_items_list[0]);

div_scroll.style.width = div_items_list[0].clientWidth + "px";
item_height = div_items_list[0].clientHeight;

p = absolutePoint(div_panel);
with(div_items.style) {
left = p[0] + "px";
top = p[1] + "px";
width = div_panel.clientWidth;
height = div_panel.clientHeight;
}
/**
* 界面改变
*/
function doChange() {
if (!item_height) return;
var i, div;
if (height != div_panel.clientHeight) {
height = div_panel.clientHeight;
view_count = parseInt(height / item_height);
for (i = div_items_list.length; i < view_count; i++) {
div = $C("div");
div.className = "item" + (i % 2 == 0 ? "" : " odd");
div_items.appendChild(div);
div_items_list.push(div);
}
for (i = 0; i < div_items_list.length; i++) {
div_items_list[i].style.display = i < view_count ? "" : "none";
}
div_scroll.style.height = div_panel.clientHeight + options.count - view_count + "px";
console.log(["view_count", view_count]);
}
div_items.scrollLeft = div_panel.scrollLeft;
if (!options.ondrawitem) return;
i = Math.min(view_count, div_items_list.length);
while(i--) {
// 重新绘制
options.ondrawitem(i + div_panel.scrollTop, div_items_list[i]);
}
}

doChange();
this.doChange = doChange;
/**
* 释放Dom对象
*/
this.dispose = function() {
var i = freed.length;
while(i--) {
freed[i].parentNode.removeChild(freed[i]);
}
i = freed.length;
while(i--) {
div_items_list[i].parentNode.removeChild(div_items_list[i]);
}
}
}
function format(template, json) {
if (!json) return template;
return template && template.replace(/\$\{(.+?)\}/g, function() {
return json[arguments[1]];
})
}
window.onload = function() {
var i = 100000, data = new Array(i);
while(i--) {
data[i] = { index: i, random: Math.random(), key: (+new Date()).toString(36) };
}
var listview = new ListView({
count: data.length,
ondrawitem: function(i, div) {
div.innerHTML = format("<em>${index}</em> <span class=\"red\">${random}</span> <span class=\"green\">${key}</span>", data[i]);
}
});

var asc = 1;
document.getElementById("sort_index").onclick = function() {
asc = -asc;
data.sort(function(a, b) {
return (a.index - b.index) * asc;
});
listview.doChange();
}
document.getElementById("sort_random").onclick = function() {
asc = -asc;
data.sort(function(a, b) {
return (a.random - b.random) * asc;
});
listview.doChange();
}
};
</script>
</body>
</html>


抛砖引玉,希望能出现更多精彩应用。
...全文
5369 264 打赏 收藏 转发到动态 举报
写回复
用AI写文章
264 条回复
切换为时间正序
请发表友善的回复…
发表回复
随S风 2011-09-18
  • 打赏
  • 举报
回复
太厉害了
a764777416 2011-09-12
  • 打赏
  • 举报
回复
每日一回。
shuchunsuper 2011-07-28
  • 打赏
  • 举报
回复
很好,,,,
jhrxx 2010-12-29
  • 打赏
  • 举报
回复

不错不错
hellsb 2010-12-28
  • 打赏
  • 举报
回复
定,JHF
西瓜爱吃橘子 2010-12-27
  • 打赏
  • 举报
回复
顶完之后再看!
xyz378704 2010-12-27
  • 打赏
  • 举报
回复
FF和IE8下10W数据的类似的实现方法多种,如直接innerHTML写上千条数据,这样比每次创建DOM对象效率更加高效,IE6下,数据的初始化是个问题,太慢
dodont 2010-12-27
  • 打赏
  • 举报
回复
这个不错,正要做相应的东西。
超级大笨狼 2010-12-27
  • 打赏
  • 举报
回复
好思路,现在围脖只是往上加,没有删除视野外的。
linxisheng 2010-12-26
  • 打赏
  • 举报
回复
如果用户不要下拉条呢
pb8 2010-12-26
  • 打赏
  • 举报
回复
pilicat 2010-12-25
  • 打赏
  • 举报
回复
谢谢分享,受教了。
skyctr 2010-12-24
  • 打赏
  • 举报
回复
感谢楼主分享!!顶一下
wangtiantian23 2010-12-24
  • 打赏
  • 举报
回复
太经典了!学些收藏了!
aressheng 2010-12-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 effun 的回复:]
这种功能我早就在自用的控件里实现了,当时的灵感来自于WinForms的ListView控件,它的虚拟模式可以提供大数据量的显示。可虽然解决了显示的问题,但实际在使用中至少有两个现实的问题,这里假设真有十万条数据:
1、假如一条记录50个字节,十万条数据就有5M,怎么样才能把这么大的数据量以最小的消耗下载到浏览器中呢?我所能想到的办法是分页并按需下载,也就是滚动条滚动到哪页就下载哪页的数据,但这样……
[/Quote]

说的很好啊。所以根本之道还是要在服务器端对信息进行挑选。再返回到客户端,而不能抓一堆数据到客户端再挑选,即便局域网也扛不住啊。
奋斗吧 2010-12-24
  • 打赏
  • 举报
回复
不错,大牛
liangtiana 2010-12-24
  • 打赏
  • 举报
回复
bucuo,好东西啊
cchaha 2010-12-24
  • 打赏
  • 举报
回复
好思路,谢谢分享
扎根梦想 2010-12-24
  • 打赏
  • 举报
回复
我已经在项目中使用这种技术了,客户反应还可以
Gingk0 2010-12-23
  • 打赏
  • 举报
回复
不错 感谢分享
加载更多回复(165)

87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧