在Ajax动态加载数据的实际应用中,大家都习惯了一种思维方式:一条数据创建一行。
于是如果数量大的时候,一次性要加载完数据的话,浏览器就会卡上半天受Flex的DataGrid控件的启发,在Flex的DataGrid控件中,展示数据的方法并不是有多少条数据就创建多少行,它最多只创建你在界面上所看到的十几二十行(假设为n行),如果数据多的话,在滚动过程中,会从数据中抽取你应该看到的这n行数据,重新展示在已经创建好的那n行控件中。
也就是说,Flex的DataGrid控件中,我们实际上看到的仅仅是那n行控件,只是它们展示的数据是根据滚动条状态来筛选出来的。所以,如果在JS中,也用类似的方法实现,那么就是上万条数据,可能也只要创建几十个Dom而已,效率自然快得多了。
废话不多说,上代码。首先,需要一个滚动条function Scrollbar() {
this.options = {
total: 0, //数据总数
pos: 0, //当前滚动位置
itemSize: 20, //单项尺寸
size: 200 //控件尺寸
};
}
Scrollbar.prototype = (function() {
function setOptions(options) {
for (var attr in options) {
this.options[attr] = options[attr];
}
Refresh(this);
}
function Refresh(_this) {
if (!_this.created) return; //设置控件高度
_this.bar.style.height = _this.options.size + "px"; //设置内容高度
var ch = _this.options.total * _this.options.itemSize;
_this.content.style.height = ch + "px";
}
//获取滚动位置
function getPos() {
var top = this.bar.scrollTop;
var pos = parseInt(top / this.options.itemSize);
return pos;
}
//每页可展示的数据数量
function getPageItems() {
return this.options.size / this.options.itemSize;
}
//滚动事件响应
function OnScroll(_this) {
var pos = _this.getPos();
if (pos == _this.options.pos) return;
_this.options.pos = pos;
_this.onScroll(pos);
} //滚动条创建
function CreateAt(dom) {
var _this = this; var bar = document.createElement("div");
var content = document.createElement("div");
bar.appendChild(content); bar.style.width = "19px";
bar.style.overflowY = "scroll";
bar.style.overflowX = "hidden";
if (bar.attachEvent) {
bar.attachEvent("onscroll", function() { OnScroll(_this); });
}
else {//firefox兼容
bar.addEventListener("scroll", function() { OnScroll(_this); }, false);
}
content.style.backgroundColor = "white";
content.style.width = "1px"; this.bar = bar;
this.content = content; if (typeof (dom) == "string") {
dom = document.getElementById(dom);
}
dom.innerHTML = "";
dom.appendChild(this.bar);
this.created = true;
Refresh(this);
} return {
setOptions: setOptions,
CreateAt: CreateAt,
getPos: getPos,
getPageItems: getPageItems,
onScroll: null //模拟滚动条事件
};
})();
页面代码<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>表格控件</title> <script src="Scrollbar.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
var data = [];
//创建一万条示例数据
for (var i = 0; i < 10000; i++) {
var row = { id: i, text: "text" + i };
data.push(row);
} //创建滚动条
var scrbar = new Scrollbar();
window.onload = function() {
scrbar.CreateAt("divScroll");
scrbar.setOptions({ total: 10000,size:300 });
scrbar.onScroll = function(pos) {
ShowData(pos);
} //获取模板
var items = scrbar.getPageItems();
var tpl = document.getElementById("trTpl");
tpl.parentNode.removeChild(tpl); //仅创建所看到的几十行表格,所以自然快得多
var list = document.getElementById("tblList");
for (var i = 0; i < data.length && i < items; i++) {
var nr = tpl.cloneNode(true); //从模板行复制新行
list.appendChild(nr);
}
ShowData(scrbar.getPos());
}
//根据滚动条,展示数据
function ShowData(pos) {
var n=scrbar.getPageItems();
var rows=document.getElementById("tblList").rows;
for (var i = 0; i < n; i++) {
var row = rows[i];
var item = data[i + pos];
row.cells["tdID"].innerHTML = item["id"];
row.cells["tdText"].innerHTML = item["text"];
}
}
</script>
</head>
<body>
<div id="divScroll" style="float:right">
</div>
<table border="1">
<!--行标题-->
<thead><tr>
<th>ID</th>
<th>Text</th>
</tr></thead>
<!--数据展示区-->
<tbody id="tblList"><tr id="trTpl">
<td id="tdID"> </td>
<td id="tdText"> </td>
</tr></tbody>
</table>
</body>
</html>OK!上万条数据,也是瞬间的事
当然,页面很粗糙,不过加点JS代码把那个滚动条和表格对齐一下,也就差不多了。
代码还没封装好,以后再慢慢封装了
而且,还轻易地解决了一个常见问题:固定表格的标题行,哈哈。
代码简陋,见笑了
于是如果数量大的时候,一次性要加载完数据的话,浏览器就会卡上半天受Flex的DataGrid控件的启发,在Flex的DataGrid控件中,展示数据的方法并不是有多少条数据就创建多少行,它最多只创建你在界面上所看到的十几二十行(假设为n行),如果数据多的话,在滚动过程中,会从数据中抽取你应该看到的这n行数据,重新展示在已经创建好的那n行控件中。
也就是说,Flex的DataGrid控件中,我们实际上看到的仅仅是那n行控件,只是它们展示的数据是根据滚动条状态来筛选出来的。所以,如果在JS中,也用类似的方法实现,那么就是上万条数据,可能也只要创建几十个Dom而已,效率自然快得多了。
废话不多说,上代码。首先,需要一个滚动条function Scrollbar() {
this.options = {
total: 0, //数据总数
pos: 0, //当前滚动位置
itemSize: 20, //单项尺寸
size: 200 //控件尺寸
};
}
Scrollbar.prototype = (function() {
function setOptions(options) {
for (var attr in options) {
this.options[attr] = options[attr];
}
Refresh(this);
}
function Refresh(_this) {
if (!_this.created) return; //设置控件高度
_this.bar.style.height = _this.options.size + "px"; //设置内容高度
var ch = _this.options.total * _this.options.itemSize;
_this.content.style.height = ch + "px";
}
//获取滚动位置
function getPos() {
var top = this.bar.scrollTop;
var pos = parseInt(top / this.options.itemSize);
return pos;
}
//每页可展示的数据数量
function getPageItems() {
return this.options.size / this.options.itemSize;
}
//滚动事件响应
function OnScroll(_this) {
var pos = _this.getPos();
if (pos == _this.options.pos) return;
_this.options.pos = pos;
_this.onScroll(pos);
} //滚动条创建
function CreateAt(dom) {
var _this = this; var bar = document.createElement("div");
var content = document.createElement("div");
bar.appendChild(content); bar.style.width = "19px";
bar.style.overflowY = "scroll";
bar.style.overflowX = "hidden";
if (bar.attachEvent) {
bar.attachEvent("onscroll", function() { OnScroll(_this); });
}
else {//firefox兼容
bar.addEventListener("scroll", function() { OnScroll(_this); }, false);
}
content.style.backgroundColor = "white";
content.style.width = "1px"; this.bar = bar;
this.content = content; if (typeof (dom) == "string") {
dom = document.getElementById(dom);
}
dom.innerHTML = "";
dom.appendChild(this.bar);
this.created = true;
Refresh(this);
} return {
setOptions: setOptions,
CreateAt: CreateAt,
getPos: getPos,
getPageItems: getPageItems,
onScroll: null //模拟滚动条事件
};
})();
页面代码<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>表格控件</title> <script src="Scrollbar.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
var data = [];
//创建一万条示例数据
for (var i = 0; i < 10000; i++) {
var row = { id: i, text: "text" + i };
data.push(row);
} //创建滚动条
var scrbar = new Scrollbar();
window.onload = function() {
scrbar.CreateAt("divScroll");
scrbar.setOptions({ total: 10000,size:300 });
scrbar.onScroll = function(pos) {
ShowData(pos);
} //获取模板
var items = scrbar.getPageItems();
var tpl = document.getElementById("trTpl");
tpl.parentNode.removeChild(tpl); //仅创建所看到的几十行表格,所以自然快得多
var list = document.getElementById("tblList");
for (var i = 0; i < data.length && i < items; i++) {
var nr = tpl.cloneNode(true); //从模板行复制新行
list.appendChild(nr);
}
ShowData(scrbar.getPos());
}
//根据滚动条,展示数据
function ShowData(pos) {
var n=scrbar.getPageItems();
var rows=document.getElementById("tblList").rows;
for (var i = 0; i < n; i++) {
var row = rows[i];
var item = data[i + pos];
row.cells["tdID"].innerHTML = item["id"];
row.cells["tdText"].innerHTML = item["text"];
}
}
</script>
</head>
<body>
<div id="divScroll" style="float:right">
</div>
<table border="1">
<!--行标题-->
<thead><tr>
<th>ID</th>
<th>Text</th>
</tr></thead>
<!--数据展示区-->
<tbody id="tblList"><tr id="trTpl">
<td id="tdID"> </td>
<td id="tdText"> </td>
</tr></tbody>
</table>
</body>
</html>OK!上万条数据,也是瞬间的事
当然,页面很粗糙,不过加点JS代码把那个滚动条和表格对齐一下,也就差不多了。
代码还没封装好,以后再慢慢封装了
而且,还轻易地解决了一个常见问题:固定表格的标题行,哈哈。
代码简陋,见笑了
解决方案 »
- javascript 变量名是另一个变量的值
- javascript对象的问题
- 求一个像本论坛发帖后提交的效果(提示消息框和刷新页面)的例子!!谢谢啦
- 根据面试和现在自己公司用的比较多
- firfox 下 属性 display="none" 的节点 找不到怎么办?
- 仿百度提示框的问题
- 请问如何让用户打开IE时,出现安装插件的窗口(就象浏览一些网站时出现的插件下载窗口一样)?(急!)
- 在xml文档中,如何取得某个元素所包含的所有子元素??
- 使用title做出tips效果时,如何使增加tips停留时间?
- 如何实在选择某个下拉框内的条目?
- 请问下面语句是什么意思?
- 我想学习一下javascript,大家能推荐下教材吗?
不过有个疑问 如果此时频繁的拖动滚动条 时间密度大 横向数据量也大 拖动时会多次触发数据库查询程序,在时间密度中是否能很好的显示也应该是个问题。当然应该可以标记鼠标按下与松开来实现一次滚动调用一次AJAX,但可以对于苛刻的用户体验度来说又不尽人意了。
找个空测试一下。说的不对还请拍砖。
我也有这疑惑 没用过FLEX 所以不知道效果如何 但如果拖动很频繁 密度大和数据库交互也就频繁了。
当然,横向数据量也大的时候,用控制一下表格的宽度就行了。
这个例子仅仅是展示了一个思路,我还没真正把它封装好。
再次证明了MVC的优势
希望楼主开发成 jquery插件
var list = document.getElementById("tblList");
for (var i = 0; i < data.length && i < items; i++) {
var nr = tpl.cloneNode(true); //从模板行复制新行
list.appendChild(nr);
}
这里换用document.createDocumentFragment()这个不知道好些不
占用的很高。
http://topic.csdn.net/u/20100310/18/8bb1dd36-4b1c-480d-a89f-be302163dc57.html?12500