javascript表格处理案例研究
摘 要:随着网页开发的流行,一些基础的开发过程变得越来越频繁,如数据的显示功能,在数据的显示过程中,往往采用表格来批量显示数据,如学生信息表、学生成绩表、订单状态表、物流跟踪表等都采用表格来显示数据。本文试图发表关于javascript处理表格的一个案例,用javaScript语言封装表格的数据处理功能。提供源码、详细设计、编程实践。
文 章 分 类:javascript编程实践;javascript基础;
标签:javascript基础;组件化
关 键 字:表格处理;javascirpt;数据显示
日 期:2022年1月28日 星期五
1、问题描述
在网页开发中,基础数据的管理和维护是一项重要的任务,基础数据具有数据量大、数据长度短、易于显示等特点,在基础数据的显示方面往往采用表格来显示数据,表格是一种显示关系型数据的工具,大大的加强了数据的直观性、可维护性和易读性,所以表格处理程序是一种可复用性高、可实用性强的程序,它能够对网页开发中基础数据的管理和维护模块的开发起到非常重要的作用,这些作用体现在快捷开发、可复用性高、实用性强和易读性高等方面。一般来说,表格处理程序需具备以下几个方面的功能:
(1)数据加载
数据加载指表格应该能够显示数据。
(2)数据处理
数据处理指表格处理程序必须提供处理数据的接口,如数据的增删改查,重新加载数据等功能。
(3)表格样式处理
表格样式处理是对表格的美化过程,一个好的表格样式可以增强用户的体验。
2、设计思路
数据加载是将一定格式、一定量的数据显示在表格上的过程,这个过程可用HTML的table标签来显示表格,用tr标签来表示行数据,用td标签来显示列数据,
数据处理是对表格上的数据的进行增删改查以及重新加载的过程,这个过程需要用javacript语言来实现。
表格的样式处理则由css来完成。
3、整体设计
数据的加载过程需要设置数据的格式和数量,这对于初级开发者来说无法考虑到用什么样的数据格式才能满足所有的业务场景,一般来说数据的格式应该包含以下基本信息。
(1)表格的行数和列数
(2)表格的表头设置
(3)表格的主体数据
(4)主体数据的基本操作
对于表格的行数和列数以及主体数据可用一个二维数组来表示,在这个二维数组中,每一项是一个一维数组,这个一维数组就表示该表格中对应的一行数据,而这个一维数组的每项就对应该表格中对应行的每列数据,这样二维数组的长度就对应表格的行数,二维数组中每项对应的一维数组的长度就对应了表格的列数。
由于我们有时需要对表格中某行数据进行相应的处理,所以表格需要增加一列操作列来表示某行数据对应的操作,这些操作由一系列的按钮构成,假设这些操作对应的按钮在一个集合{btn1,btn2,btn3,...,btnn}中,那么表格对应的操作列可用一个二维布尔数组表示,即
[[true,true,true,...,false],
...,
[true,true,true,...,false]]
该二维数组的行数和列数分别与表格的主体数据的行数和操作列对应的可操作集合的长度一致,该二维数组的数据表示该行数据包含或者不包含某项操作,即o[i][j] = true|false,表示表格中第i行包括或者不包括第j项操作,如果包含,则o[i][j] = true,如果不包含,则o[i][j]=false。
对于表格表头设置,表格的表头包括表格的列属性值和该列的宽度,如一个学生成绩表的表头应该包含一下几个属性值,即[<学生姓名>,<学生学号>,<科目>,<成绩>,<年级排名>] 等。
4、详细设计
/*表格基本配置*/
var tableconfig = {
id:...,
colN:...,
width:...,
data:...,
title:...,
head:...,
btns:...,
}
/*表格基本配置属性详解*/
属性 | 类型 | 说明 |
id | string | 页面中表格元素的id值 |
colN | int | 页面中表格元素的列的数量 |
width | string | 页面中表格元素的宽度 |
data | 二维数组 | 页面中表格元素的数据 |
title | 二维数组 | 页面中表格元素的表头设置 |
head | string | 页面中表格元素的head |
btns | json | 页面中表格元素的行的操作 |
/*表格基本配置属性之btns属性详解*
属性 | 类型 | 说明 |
title | string | 操作按钮的名称 |
index | int | 操作按钮的下标 |
handle | function | 操作按钮的执行函数 |
Xbtn | json | X表示操作按钮的简称,用英文表示,Xbtn的json格式中包含了title、index和handle即以上三个属性,X可任意命名,btns中可含多个Xbtn |
/*表格基本配置属性之handle属性详解*
属性 | 类型 | 说明 |
i | int | 操作按钮对应的行数的下标 |
index | int | 该行对相应操作按钮的下标 |
/*父类表格基本配置属性详解*
属性 | 类型 | 说明 |
pagepre | int | 表格每页可显示的数据条数,默认为10 |
skin | string | 表格对应的皮肤名 |
hasOrder | boolean | 规定表格每行是否显示行下标 |
hasCheckbox | boolean | 规定表格每行是否可选 |
load | function | 表格加载时每行数据的展示层执行函数 |
reload | function | 表格数据重新加载函数,执行时表格将被重置 |
selected | function | 当表格每行可选时,提供的获取被选择行的函数 |
next | function | 获取下一页的表格数据 |
prev | function | 获取上一页的表格数据 |
to | function | 跳转到任何一页的表格数据 |
注:父类表格基本配置属性由表格处理程序提供,开发者可覆盖
/*父类表格基本配置属性之load函数详解*
属性 | 类型 | 说明 |
i | int | 展示层执行函数加载时的行的下标值 |
data | 一维数组 | 展示层加载函数执行时的行对应的数据 |
/*父类表格基本配置属性之reload函数详解*
属性 | 类型 | 说明 |
i | int | 展示层执行函数加载时的行的下标值 |
data | 一维数组 | 展示层加载函数执行时的行对应的数据 |
configdata | 二维数组 | 重新加载数据时新数据 |
注:reload函数的参数为可选参,当为一个参数时表示重新加载整个表格,当为两个参数时表示重新加载i对应行的数据。
5、源程序设计
fe.js
(function(FE) {
FE.config = {
tableSettings : {
pagePre : 10,
skin : "sky_table",
hasOrder : true,
hasCheckBox : true,
theme : {
th : {
font : [ 18, "黑体", "#FFFFFF" ],
style : [ "center" ]
},
td : {
font : [ 16, "新宋体", "black" ],
style : [ "left" ]
},
tr : {
height : 24,
}
},
reload : function(data) {
var id = this.getAttribute("id");
window[id + "_tableSettings"].data = data;
this.innerHTML = "";
FE.createTable(window[id + "_tableSettings"]);
}
}
};
FE.extend = function(obj, fnName, fn) {
obj[fnName] = fn;
}
FE.createTable = function(tableSettings) {
var settings = FE.config.tableSettings || tableSettings;
var _table = null;
for ( var setting in tableSettings) {
settings[setting] = tableSettings[setting];
}
console.info(settings);
var _tableHead = document.createElement("thead");
var _tableBody = document.createElement("tbody");
if (settings.id) {
var _table = FE("#" + settings.id);
_table.appendChild(_tableHead);
_table.appendChild(_tableBody);
_table.setAttribute("border", "0");
if (settings.skin) {
_table.addClass(settings.skin);
}
window[settings.id + "_tableSettings"] = settings;
FE.extend(_table, "reload", FE.config.tableSettings.reload);
}
if (settings.colN) {
var _tr = document.createElement("tr");
_tr.style.height = settings.theme.tr.height;
if (settings.hasOrder) {
var _th = document.createElement("th");
if (settings.hasCheckBox) {
_th.innerHTML = "全选";
}
_tr.appendChild(_th);
}
if (settings.hasCheckBox) {
var _th = document.createElement("th");
var _input = document.createElement("input");
_input.setAttribute("id", "all");
_input.setAttribute("type", "checkbox");
_th.appendChild(_input);
_tr.appendChild(_th);
}
for ( var i = 0; i < settings.colN; i++) {
var _th = document.createElement("th");
_th.style.fontSize = settings.theme.th.font[0];
_th.style.fontFamily = settings.theme.th.font[1];
_th.style.fontWeight = "bold";
_th.style.color = settings.theme.th.font[2];
_th.innerHTML = settings.title[i];
_th.style.width = settings.width[i];
_tr.appendChild(_th);
}
if (settings.btns) {
var _th = document.createElement("th");
_th.style.fontSize = settings.theme.th.font[0];
_th.style.fontFamily = settings.theme.th.font[1];
_th.style.fontWeight = "bold";
_th.style.color = settings.theme.th.font[2];
_th.innerHTML = "操作";
_tr.appendChild(_th);
}
_tableHead.appendChild(_tr);
}
if (settings.data) {
for ( var i = 0; i < settings.data.length; i++) {
var _tr = document.createElement("tr");
_tr.style.height = settings.theme.tr.height;
if (i % 2 != 0 && settings.skin) {
_tr.className = settings.skin + "_tr";
}
if (settings.hasOrder) {
var _td = document.createElement("td");
_td.style.textAlign = "center";
_td.innerHTML = i + 1;
_tr.appendChild(_td);
}
if (settings.hasCheckBox) {
var _td = document.createElement("td");
var _input = document.createElement("input");
_input.setAttribute("id", "checkbox" + i);
_input.setAttribute("type", "checkbox");
_td.appendChild(_input);
_tr.appendChild(_td);
}
var len = settings.btns ? settings.data[i].length - 1
: settings.data[i].length;
for ( var j = 0; j < len; j++) {
var _td = document.createElement("td");
_td.style.fontSize = settings.theme.td.font[0];
_td.style.fontFamily = settings.theme.td.font[1];
_td.style.color = settings.theme.td.font[2];
_td.innerHTML = settings.data[i][j];
_tr.appendChild(_td);
}
if (settings.btns) {
var _td = document.createElement("td");
for ( var btn in settings.btns) {
var _btn = document.createElement("input");
_btn.setAttribute("type", "button");
var index = settings.btns[btn].index;
if (settings.btns[btn].title) {
_btn
.setAttribute("value",
settings.btns[btn].title);
}
if (settings.btns[btn].handle) {
FE.extend(_table, btn + "_handle",
settings.btns[btn].handle);
_btn.setAttribute("row", i);
_btn.setAttribute("index", index);
_btn.setAttribute("btn", btn);
}
if (settings.btns
&& settings.data[i][settings.data[i].length - 1][index]) {
_td.appendChild(_btn);
}
}
_tr.appendChild(_td);
}
_tr.onmouseover = function() {
var _className = this.className;
this.className = settings.skin + "_tr_mouseover";
this.setAttribute("old", _className);
}
_tr.onmouseout = function() {
this.className = this.getAttribute("old");
}
_tableBody.appendChild(_tr);
}
}
_table.onclick = function(event, row, index) {
if (event.target.localName == "input") {
var row = event.target.getAttribute("row");
var index = event.target.getAttribute("index");
var btn = event.target.getAttribute("btn");
this[btn + "_handle"](row, index);
}
}
return _table;
};
window.FE = FE;
})(node);
function node(selector) {
var result = getElement(selector);
if (!result.length) {
FE.extend(result, "addClass", addClass);
FE.extend(result, "removeClass", removeClass);
FE.extend(result, "valueOfStyle", valueOfStyle);
} else {
for ( var i = 0; i < result.length; i++) {
FE.extend(result[i], "addClass", addClass);
FE.extend(result[i], "removeClass", removeClass);
FE.extend(result[i], "valueOfStyle", valueOfStyle);
}
}
return result;
}
function getElement(selector) {
if ((typeof selector) == "string") {
var result = null;
var selectors = selector.split(" ");
for ( var i = 0; i < selectors.length; i++) {
if (selectors[i].indexOf("#") == 0) {
result = document.getElementById(selectors[i].substring(1));
}
if (selectors[i].indexOf("<") == 0 && selectors[i].indexOf(">") > 0) {
if (selectors[i].indexOf(".") > 0) {
var _selector = selectors[i].split(".");
var tagName = _selector[0].substring(1,
_selector[0].length - 1);
result = result ? result.getElementsByTagName(tagName)
: document.getElementsByTagName(tagName);
if (result) {
var doms = [];
for ( var i = 0; i < result.length; i++) {
var className = result[i].className;
if (className.indexOf(_selector[1]) >= 0) {
doms.push(result[i]);
}
}
return doms;
}
} else {
var tagName = selectors[i].substring(1,
selectors[i].length - 1);
if (result && (typeof result) == "object") {
result = result.getElementsByTagName(tagName);
} else {
result = document.getElementsByTagName(tagName);
}
}
}
}
return result;
}
}
function addClass(className) {
var _className = this.className;
this.className = _className + " " + className;
}
function removeClass(className) {
var _className = this.className;
if (_className.indexOf(className) >= 0) {
var classes = _className.split(" ");
var classNameStr = "";
for ( var i = 0; i < classes.length; i++) {
if (classes[i] == className) {
continue;
} else {
classNameStr += classes[i] + " ";
}
}
this.className = classNameStr;
}
}
function valueOfStyle() {
if (elements.length == 1) {
return this.style[elements[0]];
} else {
this.style[elements[0]] = elements[1];
}
}
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>表格处理</title>
<script type="text/javascript" src="js/base/1.0.3/fe.js"></script>
<link rel="stylesheet" type="text/css" href="css/base/1.0.1/fe.css">
<script type="text/javascript">
window.onload = function() {
var tableSettings = {
id:"mytable",
colN:2,
data:[["createElement(tagName)","创建一个标签名为tagName的新元素节点",[true]],
["A.appendChild(B)","把B节点添加至A节点的末尾",[true]],
["insertBefore(A,B)","把A节点插入到B节点之前",[true]],
["cloneNode(deep)","复制某个指定的的节点",[true]]],
title:["名称","描述"],
width:["300","600"],
btns:{
delbtn: {
title:"删除",
index:0,
handle:function(row,index) {
console.info(row);
this.reload([["createElement","创建一个标签名为tagName的新元素节点",[true]],
["A.appendChild(B)","把B节点添加至A节点的末尾",[true]],
["insertBefore(A,B)","把A节点插入到B节点之前",[true]],
["cloneNode(deep)","复制某个指定的的节点",[true]]]);
}
}
}
};
var _table = FE.createTable(tableSettings);
}
</script>
</head>
<body>
<div id="mytable"></div>
</body>
</html>
fe.css
.sky_table {
border: 1px solid blue;
border-radius: 10px;
}
.sky_table thead tr {
background-color: #FF9900
}
.sky_table_tr {
background-color: #0099CC
}
.sky_table_tr_mouseover {
background-color: #99CCFF
}