在 Ajax 动态加载数据的实际应用中, 大家都习惯了一种思维方式: 一条数据创建一行.
于是如果数量大的时候, 一次性要加载完数据的话, 浏览器就会卡上半天
受 Flex 的 DataGrid 控件的启发, 在 Flex 的 DataGrid 控件中, 展示数据的方法并不是有多少条数据就创建多少行, 它最多只创建你在界面上所看到的十几二十行 (假设为 n 行), 如果数据多的话, 在滚动过程中, 会从数据中抽取你应该看到的这 n 行数据, 重新展示在已经创建好的那 n 行控件中.
也就是说, Flex 的 DataGrid 控件中, 我们实际上看到的仅仅是那 n 行控件, 只是它们展示的数据是根据滚动条状态来筛选出来的.
所以, 如果在 JS 中, 也用类似的方法实现, 那么就是上万条数据, 可能也只要创建几十个 Dom 而已, 效率自然快得多了.
废话不多说, 上代码. 首先, 需要一个滚动条
- JScript code
- 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 // 模拟滚动条事件
- };
- })();
页面代码
HTML code
- <!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 代码把那个滚动条和表格对齐一下, 也就差不多了.
代码还没封装好, 以后再慢慢封装了
而且, 还轻易地解决了一个常见问题: 固定表格的标题行, 哈哈....
代码简陋, 见笑了
来源: http://fogandsun.blog.163.com/blog/static/36658874201029101414245