jQuery EasyUI框架中的Datagrid數(shù)據(jù)表格組件結(jié)構(gòu)詳解
基礎(chǔ)DOM結(jié)構(gòu)
什么叫“完整的基礎(chǔ)DOM結(jié)構(gòu)”,這里“基礎(chǔ)”的意思是指這個(gè)結(jié)構(gòu)不依賴具體數(shù)據(jù),不依賴Datagrid的view屬性,只要存在Datagrid實(shí)例就會存在這樣的基礎(chǔ)DOM結(jié)構(gòu);而“完整”的意思是指在凍結(jié)列,凍結(jié)行,標(biāo)題,footer,分頁這些功能塊都存在時(shí)候的DOM結(jié)構(gòu)。
要搞清楚Datagrid的工作原理,這個(gè)DOM結(jié)構(gòu)必須要爛熟于胸的,我們直接來看這個(gè)“基礎(chǔ)完整DOM結(jié)構(gòu)”是什么樣子的:
<!-- datagrid的最外層容器,可以使用$(target).datagrid('getPanel')或者$.data(target,'datagrid').panel得到這個(gè)DOM對象,這個(gè)DOM上其實(shí)承載了panel組件-->
<div class="panel datagrid">
<!-- datagrid的標(biāo)題區(qū)域容器,對應(yīng)于panel組件的header部分,可以使用$(target).datagrid('getPanel').panel('header')得到這個(gè)DOM對象-->
<div class="panel-header">
<div class="panel-title"></div>
<div class="panel-tool"></div>
</div>
<!-- datagrid的主體區(qū)域容器,對應(yīng)于panel組件的body部分,可以使用$(target).datagrid('getPanel').panel('body')得到這個(gè)DOM對象-->
<div class="datagrid-wrap panel-body">
<!--工具欄-->
<div class="datagrid-toolbar"></div>
<!-- datagrid視圖部分的容器,這是datagrid組件DOM結(jié)構(gòu)的核心,其基礎(chǔ)視圖結(jié)構(gòu)跟datagrid的view屬性無任何關(guān)系。-->
<!-- 對應(yīng)dc.view -->
<div class="datagrid-view">
<!-- div.datagrid-view1負(fù)責(zé)展示凍結(jié)列部分(包含行號或者frozenColumns)的數(shù)據(jù)-->
<!-- 對應(yīng)dc.view1 -->
<div class="datagrid-view1">
<!--列標(biāo)題部分-->
<div class="datagrid-header">
<!-- 對應(yīng)dc.header1 -->
<div class="datagrid-header-inner">
<!--樣式里有htable關(guān)鍵字,h代表header的意思-->
<table class="datagrid-htable">
<tbody>
<tr class="datagrid-header-row"></tr>
</tbody>
</table>
</div>
</div>
<!--列數(shù)據(jù)部分-->
<div class="datagrid-body">
<!-- 對應(yīng)dc.body1 -->
<div class="datagrid-body-inner">
<!--frozenRows部分(有數(shù)據(jù)才會有這個(gè)table,故不屬于基礎(chǔ)DOM結(jié)構(gòu)),固定行是1.3.2版本之后才加的功能,注意datagrid-btable-frozen關(guān)鍵樣式,btable代碼body table的意思-->
<table class="datagrid-btable datagrid-btable-frozen"></table>
<!--普通rows部分(有數(shù)據(jù)才會有這個(gè)table,故不屬于基礎(chǔ)DOM結(jié)構(gòu))-->
<table class="datagird-btable"></table>
</div>
</div>
<!--footer部分-->
<div class="datagrid-footer">
<!-- 對應(yīng)dc.footer1 -->
<div class="datagrid-footer-inner">
<!--ftable代表footer table的意思-->
<table class="datagrid-ftable"></table>
</div>
</div>
</div>
<!-- div.datagrid-view2負(fù)責(zé)展示非凍結(jié)列部分的數(shù)據(jù),大家注意到凍結(jié)列和普通列視圖是分開的,也就是說凍結(jié)列和普通列是在不同表格中展示的,這樣會產(chǎn)生一個(gè)問題,那就是兩個(gè)表格行高之間的同步問題。-->
<!-- 對應(yīng)dc.view2 -->
<div class="datagrid-view2">
<!--列標(biāo)題部分-->
<div class="datagrid-header">
<!-- 對應(yīng)dc.header2 -->
<div class="datagrid-header-inner">
<table class="datagrid-htable">
<tbody>
<tr class="datagrid-header-row"></tr>
</tbody>
</table>
</div>
</div>
<!--列數(shù)據(jù)部分,注意這里并無datagrid-body-inner這個(gè)子元素,而凍結(jié)列對應(yīng)的body卻是有的,這個(gè)是細(xì)微區(qū)別-->
<!-- 對應(yīng)dc.body2 -->
<div class="datagrid-body">
<!--frozenRows部分有數(shù)據(jù)才會有這個(gè)table,故不屬于基礎(chǔ)DOM結(jié)構(gòu),固定行是1.3.2版本之后才加的功能,-->
<table class="datagrid-btable datagrid-btable-frozen"></table>
<table class="datagrid-btable"></table>
</div>
<!--footer部分-->
<div class="datagrid-footer">
<!-- 對應(yīng)dc.footer2 -->
<div class="datagrid-footer-inner">
<table class="datagrid-ftable"></table>
</div>
</div>
</div>
</div>
<!--分頁部分-->
<div class="datagrid-pager pagination"></div>
</div>
</div>
對于這個(gè)DOM結(jié)構(gòu),我在html代碼里面已經(jīng)做了簡單說明,這里提一下綁定于Datagrid宿主table上的對象的dc屬性,這個(gè)dc屬性存儲了對DOM結(jié)構(gòu)里不同部分的引用,獲取dc屬性的方法:
$.data(target,'datagrid').dc;
而dc屬性跟DOM的對應(yīng)關(guān)系,我也在html中做了詳細(xì)注釋,請大家自行查看,這些都是我們深入認(rèn)識Datagrid組件的基礎(chǔ)。
默認(rèn)視圖分析
上面對Datagrid組件的骨架做了很詳細(xì)的描述。有了骨架還并不完整,還得有血有肉有衣服穿才行。強(qiáng)大的Datagrid組件允許我們自己定義如何在基礎(chǔ)骨架上長出健壯誘人的身體,我們只要定義Datagrid的視圖就可以實(shí)現(xiàn)。
在大多數(shù)情況下,我們并無特別要求,Datagrid給我們提供了默認(rèn)的視圖,默認(rèn)視圖被使用在90%以上的場景,所以對默認(rèn)視圖的分析顯得非常有必要。注意視圖里面定義了哪些接口,哪些方法,如果要自己寫視圖的話,最好把這些接口和方法都寫齊全。
var view = {
/**
* 填充表格主體數(shù)據(jù)(生成數(shù)據(jù)部分的各行tr)
* @param {DOM object} target datagrid宿主table對應(yīng)的DOM對象
* @param {DOM object} container 數(shù)據(jù)主體容器。包含兩個(gè)可能的值,即:
* 1.frozen部分body1,對應(yīng)的DOM對象為:div.datagrid-view>div.datagrid-view1>div.datagrid-body>div.datagrid-body-inner
* 2.常規(guī)部分body2,對應(yīng)的DOM對象為:div.datagrid-view>div.datagrid-view2>div.datagrid-body
* @param {boolean} frozen 是否是凍結(jié)列
* @return {undefined} 未返回值
*/
render: function(target, container, frozen) {
var data = $.data(target, "datagrid");
var opts = data.options;
var rows = data.data.rows;
var fields = $(target).datagrid("getColumnFields", frozen);
if(frozen) {
//如果grid不顯示rownumbers并且也沒有frozenColumns的話,直接退出。
if(!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))) {
return;
}
}
//定義表格字符串,注意這里使用了數(shù)組的join方式代替了傳統(tǒng)的"+"運(yùn)算符,在大多瀏覽器中,這樣效率會更高些。
var html = ["<table class=\"datagrid-btable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
for(var i = 0; i < rows.length; i++) {
//striped屬性,用于設(shè)置grid數(shù)據(jù)是否隔行變色,當(dāng)然了實(shí)現(xiàn)原理很簡單。
var cls = (i % 2 && opts.striped) ? "class=\"datagrid-row datagrid-row-alt\"" : "class=\"datagrid-row\"";
/**
* 表格的rowStyler屬性用于處理數(shù)據(jù)行的css樣式,當(dāng)然了這個(gè)樣式僅僅是作用于tr標(biāo)簽上。
* 這地方使用call了方法來設(shè)置上下文,如果rowStyler函數(shù)內(nèi)部使用了this的話,則this指向datagrid的宿主table對應(yīng)的DOM對象。
*/
var style = opts.rowStyler ? opts.rowStyler.call(target, i, rows[i]) : "";
var styler = style ? "style=\"" + style + "\"" : "";
/**
* rowId:行的唯一標(biāo)示,對應(yīng)于tr的id屬性,其由以下幾部分組成:
* 1.字符竄常量:"datagrid-row-r";
* 2.全局索引index:該索引值從1開始遞增,同一個(gè)datagrid組件實(shí)例擁有唯一值,如果同一頁面內(nèi)有多個(gè)datagrid實(shí)例,那么其值從1遞增分配給每個(gè)datagrid實(shí)例;
* 3.凍結(jié)列標(biāo)識frozen:該標(biāo)識用于標(biāo)示是否是凍結(jié)列(包含行號和用戶指定的frozenColumns),"1"代表凍結(jié)列,"2"代表非凍結(jié)列;
* 4.行數(shù)索引:該值才是真正代表“第幾行”的意思,該值從0開始遞增
* 如頁面內(nèi)第一個(gè)datagrid實(shí)例的非凍結(jié)列第10行數(shù)據(jù)的rowId為"datagrid-row-r1-2-9"
*/
var rowId = data.rowIdPrefix + "-" + (frozen ? 1 : 2) + "-" + i;
html.push("<tr id=\"" + rowId + "\" datagrid-row-index=\"" + i + "\" " + cls + " " + styler + ">");
/**
* 調(diào)用renderRow方法,生成行數(shù)據(jù)(行內(nèi)的各列數(shù)據(jù))。
* 這里的this就是opts.view,之所以用call方法,只是為了傳參進(jìn)去。這里我們使用this.renderRow(target,fields,frozen,i,rows[i])來調(diào)用renderRow方法應(yīng)該也是可以的。
*/
html.push(this.renderRow.call(this, target, fields, frozen, i, rows[i]));
html.push("</tr>");
}
html.push("</tbody></table>");
//用join方法完成字符創(chuàng)拼接后直接innerHTML到容器內(nèi)。
$(container).html(html.join(""));
},
/**
* [renderFooter description]
* @param {DOM object} target datagrid宿主table對應(yīng)的DOM對象
* @param {DOM object} container 可能為dc.footer1或者dc.footer2
* @param {boolean} frozen 是否為frozen區(qū)
* @return {undefined} 未返回值
*/
renderFooter: function(target, container, frozen) {
var opts = $.data(target, "datagrid").options;
//獲取footer數(shù)據(jù)
var rows = $.data(target, "datagrid").footer || [];
var columnsFields = $(target).datagrid("getColumnFields", frozen);
//生成footer區(qū)的table
var footerTable = ["<table class=\"datagrid-ftable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
for(var i = 0; i < rows.length; i++) {
footerTable.push("<tr class=\"datagrid-row\" datagrid-row-index=\"" + i + "\">");
footerTable.push(this.renderRow.call(this, target, columnsFields, frozen, i, rows[i]));
footerTable.push("</tr>");
}
footerTable.push("</tbody></table>");
$(container).html(footerTable.join(""));
},
/**
* 生成某一行數(shù)據(jù)
* @param {DOM object} target datagrid宿主table對應(yīng)的DOM對象
* @param {array} fields datagrid的字段列表
* @param {boolean} frozen 是否為凍結(jié)列
* @param {number} rowIndex 行索引(從0開始)
* @param {json object} rowData 某一行的數(shù)據(jù)
* @return {string} 單元格的拼接字符串
*/
renderRow: function(target, fields, frozen, rowIndex, rowData) {
var opts = $.data(target, "datagrid").options;
//用于拼接字符串的數(shù)組
var cc = [];
if(frozen && opts.rownumbers) {
//rowIndex從0開始,而行號顯示的時(shí)候是從1開始,所以這里要加1.
var rowNumber = rowIndex + 1;
//如果分頁的話,根據(jù)頁碼和每頁記錄數(shù)重新設(shè)置行號
if(opts.pagination) {
rowNumber += (opts.pageNumber - 1) * opts.pageSize;
}
/**
* 先拼接行號列
* 注意DOM特征,用zenCoding可表達(dá)為"td.datagrid-td-rownumber>div.datagrid-cell-rownumber"
*/
cc.push("<td class=\"datagrid-td-rownumber\"><div class=\"datagrid-cell-rownumber\">" + rowNumber + "</div></td>");
}
for(var i = 0; i < fields.length; i++) {
var field = fields[i];
var col = $(target).datagrid("getColumnOption", field);
if(col) {
var value = rowData[field];
//獲取用戶定義的單元格樣式,入?yún)ǎ簡卧裰?,?dāng)前行數(shù)據(jù),當(dāng)前行索引(從0開始)
var style = col.styler ? (col.styler(value, rowData, rowIndex) || "") : "";
//如果是隱藏列直接設(shè)置display為none,否則設(shè)置為用戶想要的樣式
var styler = col.hidden ? "style=\"display:none;" + style + "\"" : (style ? "style=\"" + style + "\"" : "");
cc.push("<td field=\"" + field + "\" " + styler + ">");
//如果當(dāng)前列是datagrid組件保留的ck列時(shí),則忽略掉用戶定義的樣式,即styler屬性對datagrid自帶的ck列是不起作用的。
if(col.checkbox) {
var styler = "";
} else {
var styler = "";
//設(shè)置文字對齊屬性
if(col.align) {
styler += "text-align:" + col.align + ";";
}
//設(shè)置文字超出td寬時(shí)是否自動換行(設(shè)置為自動換行的話會撐高單元格)
if(!opts.nowrap) {
styler += "white-space:normal;height:auto;";
} else {
/**
* 并不是nowrap屬性為true單元格就肯定不會被撐高,這還得看autoRowHeight屬性的臉色
* 當(dāng)autoRowHeight屬性為true的時(shí)候單元格的高度是根據(jù)單元格內(nèi)容而定的,這種情況主要是用于表格里展示圖片等媒體。
*/
if(opts.autoRowHeight) {
styler += "height:auto;";
}
}
}
//這個(gè)地方要特別注意,前面所拼接的styler屬性并不是作用于td標(biāo)簽上,而是作用于td下的div標(biāo)簽上。
cc.push("<div style=\"" + styler + "\" ");
//如果是ck列,增加"datagrid-cell-check"樣式類
if(col.checkbox) {
cc.push("class=\"datagrid-cell-check ");
}
//如果是普通列,增加"datagrid-cell-check"樣式類
else {
cc.push("class=\"datagrid-cell " + col.cellClass);
}
cc.push("\">");
/**
* ck列光設(shè)置class是不夠的,當(dāng)突然還得append一個(gè)input進(jìn)去才是真正的checkbox。此處未設(shè)置input的id,只設(shè)置了name屬性。
* 我們注意到formatter屬性對datagird自帶的ck列同樣不起作用。
*/
if(col.checkbox) {
cc.push("<input type=\"checkbox\" name=\"" + field + "\" value=\"" + (value != undefined ? value : "") + "\"/>");
}
//普通列
else {
/**
* 如果單元格有formatter,則將formatter后生成的DOM放到td>div里面
* 換句話說,td>div就是如來佛祖的五指山,而formatter只是孫猴子而已,猴子再怎么變化翻跟頭,始終在佛祖手里。
*/
if(col.formatter) {
cc.push(col.formatter(value, rowData, rowIndex));
}
//操,這是最簡單的簡況了,將值直接放到td>div里面。
else {
cc.push(value);
}
}
cc.push("</div>");
cc.push("</td>");
}
}
//返回單元格字符串,注意這個(gè)函數(shù)內(nèi)部并未把字符串放到文檔流中。
return cc.join("");
},
/**
* 刷新行數(shù)據(jù),只有一個(gè)行索引(從0開始),調(diào)用的updateRow方法,這里直接跳過。
* @param {DOM object} target datagrid實(shí)例的宿主table對應(yīng)的DOM對象
* @param {number} rowIndex 行索引(從0開始)
* @return {undefined} 未返回?cái)?shù)據(jù)
*/
refreshRow: function(target, rowIndex) {
this.updateRow.call(this, target, rowIndex, {});
},
/**
* 刷新行數(shù)據(jù),該接口方法肩負(fù)著同步行高,重新計(jì)算和布局grid面板等重任
* @param {DOM object} target datagrid實(shí)例的宿主table對應(yīng)的DOM對象
* @param {number} rowIndex 行索引(從0開始)
* @param {json object} 行數(shù)據(jù)
* @return {undefined} 未返回?cái)?shù)據(jù)
*/
updateRow: function(target, rowIndex, row) {
var opts = $.data(target, "datagrid").options;
var rows = $(target).datagrid("getRows");
$.extend(rows[rowIndex], row);
var style = opts.rowStyler ? opts.rowStyler.call(target, rowIndex, rows[rowIndex]) : "";
function updateTableRow(frozen) {
var fields = $(target).datagrid("getColumnFields", frozen);
//這個(gè)地方查找grid的數(shù)據(jù)主體表格(可能包含凍結(jié)列對應(yīng)的主體表格和普通列對應(yīng)的主體表格)
//getTr這個(gè)函數(shù),我在博客上介紹過,請參考:http://www.easyui.info/archives/396.html
var tr = opts.finder.getTr(target, rowIndex, "body", (frozen ? 1 : 2));
var checked = tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked");
//這里調(diào)用了renderRow方法來重新獲取當(dāng)前行的html字符串
tr.html(this.renderRow.call(this, target, fields, frozen, rowIndex, rows[rowIndex]));
tr.attr("style", style || "");
//更新的時(shí)候保留checkbox狀態(tài)(包含兩層信息:一是有ck列;二是ck列被之前就被選中)
if(checked) {
tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked", true);
}
};
//更新凍結(jié)列對應(yīng)的行
updateTableRow.call(this, true);
//更新普通列對應(yīng)的行
updateTableRow.call(this, false);
//重新布局表格面板
$(target).datagrid("fixRowHeight", rowIndex);
},
insertRow: function(target, rowIndex, row) {
var state = $.data(target, "datagrid");
//options
var opts = state.options;
//document of datagrid
var dc = state.dc;
var data = state.data;
//兼容無效的rowIndex,默認(rèn)設(shè)置為在最后一行追加
if(rowIndex == undefined || rowIndex == null) {
rowIndex = data.rows.length;
}
//為啥不跟上面的條件并到一起
if(rowIndex > data.rows.length) {
rowIndex = data.rows.length;
}
/**
* 下移rows
* @param {boolean} frozen 是否為frozen部分
* @return {undefined} 無返回值
*/
function moveDownRows(frozen) {
//1:凍結(jié)列部分;2:普通列部分
var whichBody = frozen ? 1 : 2;
for(var i = data.rows.length - 1; i >= rowIndex; i--) {
var tr = opts.finder.getTr(target, i, "body", whichBody);
//注意這地方設(shè)置了tr的"datagrid-row-index"和"id"屬性
tr.attr("datagrid-row-index", i + 1);
tr.attr("id", state.rowIdPrefix + "-" + whichBody + "-" + (i + 1));
//計(jì)算行號
if(frozen && opts.rownumbers) {
//因rowIndex從0開始,以及須插入位置以下的tr要統(tǒng)一下移,所以新行號為i+2
var rownumber = i + 2;
//有分頁的話,行號還要加上分頁數(shù)據(jù)
if(opts.pagination) {
rownumber += (opts.pageNumber - 1) * opts.pageSize;
}
tr.find("div.datagrid-cell-rownumber").html(rownumber);
}
}
};
/**
* 插入了,要插兩個(gè)地方的哦(如果你是男人,你可以笑一下)
* @param {boolean} frozen 是否是frozen部分
* @return {undefined} 未返回值
*/
function doInsert(frozen) {
var whichBody = frozen ? 1 : 2;
//這行代碼,不知道是干嘛的,怕插入得太快而早早繳械,所以才故意拖延時(shí)間的么?
var columnFields = $(target).datagrid("getColumnFields", frozen);
//構(gòu)造新插入行的id屬性
var trId = state.rowIdPrefix + "-" + whichBody + "-" + rowIndex;
var tr = "<tr id=\"" + trId + "\" class=\"datagrid-row\" datagrid-row-index=\"" + rowIndex + "\"></tr>";
if(rowIndex >= data.rows.length) {
//如果已經(jīng)有記錄,則插入tr即可
if(data.rows.length) {
//嗯哼,getTr的這個(gè)用法不多哦,未傳入行索引,第三個(gè)參數(shù)為"last",隨便的意淫一下就知道是獲取最后一行了
//然后再在最后一行后插入一行,注意了,這里用的后入式
opts.finder.getTr(target, "", "last", whichBody).after(tr);
}
//如果表格尚無記錄,則要生成表格,同時(shí)插入tr
else {
var cc = frozen ? dc.body1 : dc.body2;
cc.html("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>" + tr + "</tbody></table>");
}
}
//在rowIndex + 1前準(zhǔn)確無誤地插入,注意了,這里是前入式。
else {
opts.finder.getTr(target, rowIndex + 1, "body", whichBody).before(tr);
}
};
//下移frozen部分
moveDownRows.call(this, true);
//下移普通列部分
moveDownRows.call(this, false);
//插入frozen區(qū)
doInsert.call(this, true);
//插入普通區(qū)
doInsert.call(this, false);
//總數(shù)加1
data.total += 1;
//維護(hù)data.rows數(shù)組,這地方是插入一個(gè)數(shù)組元素了
data.rows.splice(rowIndex, 0, row);
//刷新,其中包含了重新布局grid面板等復(fù)雜得一筆的操作
//插入本是件很簡單愉快的事情,可是你得為其后果負(fù)上沉重的代價(jià)
this.refreshRow.call(this, target, rowIndex);
},
/**
* 刪除行接口
* @param {DOM object} target datagrid實(shí)例的宿主table對應(yīng)的DOM對象
* @param {number} rowIndex 行索引
* @return {undefined} 未返回值
*/
deleteRow: function(target, rowIndex) {
var state = $.data(target, "datagrid");
var opts = state.options;
var data = state.data;
function moveUpRows(frozen) {
var whichBody = frozen ? 1 : 2;
for(var i = rowIndex + 1; i < data.rows.length; i++) {
var tr = opts.finder.getTr(target, i, "body", whichBody);
//"datagrid-row-index"和"id"屬性減一
tr.attr("datagrid-row-index", i - 1);
tr.attr("id", state.rowIdPrefix + "-" + whichBody + "-" + (i - 1));
if(frozen && opts.rownumbers) {
var rownumber = i;
if(opts.pagination) {
rownumber += (opts.pageNumber - 1) * opts.pageSize;
}
tr.find("div.datagrid-cell-rownumber").html(rownumber);
}
}
};
//移除行
opts.finder.getTr(target, rowIndex).remove();
//上移frozen區(qū)
moveUpRows.call(this, true);
//上移普通區(qū)
moveUpRows.call(this, false);
//記錄數(shù)減一
data.total -= 1;
//維護(hù)data.rows數(shù)據(jù)
data.rows.splice(rowIndex, 1);
},
/**
* 默認(rèn)的onBeforeRender事件 為空
* @param {DOM object} target datagrid實(shí)例的宿主table對應(yīng)的DOM對象
* @param {array} rows 要插入的數(shù)據(jù)
* @return {undefined} 默認(rèn)未返回值
*/
onBeforeRender: function(target, rows) {},
/**
* 默認(rèn)的onAfterRender 隱藏footer里的行號和check
* @param {DOM object} target datagrid實(shí)例的宿主table對應(yīng)的DOM對象
* @return {undefined} 未返回值
*/
onAfterRender: function(target) {
var opts = $.data(target, "datagrid").options;
if(opts.showFooter) {
var footer = $(target).datagrid("getPanel").find("div.datagrid-footer");
footer.find("div.datagrid-cell-rownumber,div.datagrid-cell-check").css("visibility", "hidden");
}
}
}; - Python SqlAlchemy動態(tài)添加數(shù)據(jù)表字段實(shí)例解析
- java使用JDBC動態(tài)創(chuàng)建數(shù)據(jù)表及SQL預(yù)處理的方法
- 如何將Oracle的一個(gè)大數(shù)據(jù)表快速遷移到 Sqlserver2008數(shù)據(jù)庫(圖文教程)
- Angualrjs和bootstrap相結(jié)合實(shí)現(xiàn)數(shù)據(jù)表格table
- bootstrap table 數(shù)據(jù)表格行內(nèi)修改的實(shí)現(xiàn)代碼
- MySQL中大數(shù)據(jù)表增加字段的實(shí)現(xiàn)思路
- mysql中數(shù)據(jù)庫與數(shù)據(jù)表編碼格式的查看、創(chuàng)建及修改
- Android實(shí)現(xiàn)仿excel數(shù)據(jù)表格效果
- MySQL清空數(shù)據(jù)表的方法實(shí)例與分析
- MySQL中復(fù)制數(shù)據(jù)表中的數(shù)據(jù)到新表中的操作教程
- Oracle的數(shù)據(jù)表中行轉(zhuǎn)列與列轉(zhuǎn)行的操作實(shí)例講解
- 詳解數(shù)據(jù)庫中跨庫數(shù)據(jù)表的運(yùn)算
相關(guān)文章
jQuery EasyUi 驗(yàn)證功能實(shí)例解析
本文給大家分享jquery easyui驗(yàn)證功能的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01
jquery關(guān)于圖形報(bào)表的運(yùn)用實(shí)現(xiàn)代碼
jquery 關(guān)于圖形報(bào)表的運(yùn)用實(shí)現(xiàn)代碼,需要的朋友可以參考下。2011-01-01
在網(wǎng)站上應(yīng)該用的30個(gè)jQuery插件整理
jQuery插件是網(wǎng)頁設(shè)計(jì)師最喜歡的。從圖像滑塊,圖像畫廊和導(dǎo)航插件,它們是如此眾多,如此多樣,如此驚人的和互動可以制作美化網(wǎng)站2011-11-11
jQuery實(shí)現(xiàn)驗(yàn)證用戶登錄
這篇文章主要為大家詳細(xì)介紹了jQuery實(shí)現(xiàn)驗(yàn)證用戶登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
基于Jquery實(shí)現(xiàn)仿百度百科右側(cè)導(dǎo)航代碼附源碼下載
本篇文章給大家介紹基于jquery實(shí)現(xiàn)仿百度百科右側(cè)導(dǎo)航代碼附源碼下載,對百度百科右側(cè)導(dǎo)航代碼相關(guān)內(nèi)容感興趣的朋友可以參考下本文2015-11-11

