欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

純原生js實(shí)現(xiàn)table表格的增刪

 更新時間:2017年01月05日 15:19:48   作者:wangyuheng77  
本文主要介紹了純原生javascript實(shí)現(xiàn)table表格的增刪的方法,文章底部提供了完整的代碼。需要的朋友一起來看下吧

公司實(shí)習(xí)生問我table的增刪操作,用jQuery很簡單的實(shí)現(xiàn)了。又問我不使用jQuery,只使用js如何實(shí)現(xiàn)。

面對這種情況,我的一貫做法是‘不理解,但是支持'。

jQuery用的多了,人也懶了,但還是用js實(shí)現(xiàn)了這一操作,覺得難點(diǎn)在于IE兼容。。。

只是想找代碼看看的可以跳過分析過程,文章底部附有完整代碼。

以下是coding過程:

HTML結(jié)構(gòu)代碼

一個基本的table結(jié)構(gòu),增加了一些簡單的樣式,三個按鈕分別對應(yīng)創(chuàng)建、清空,和一個預(yù)留。

<!DOCTYPE HTML> 
<html> 
 <head> 
 <title>table</title> 
 <meta charset='utf-8' /> 
 <style type="text/css"> 
 table.base{ 
 border-collapse:collapse; 
 text-align: center; 
 border: 1px solid black; 
 } 
 table, tr, td, th{ 
 border: 1px solid black; 
 } 
 </style> 
 </head> 
 <body> 
 <div id="main-content"> 
 <table id="main-table" class="base"> 
 <thead> 
  <tr> 
  <th colspan="3">This is a table for operations by javascript</th> 
  </tr> 
  <tr> 
  <th> 
  <input type="button" value="CREATE" id="cp_btn" onclick="createTr()" /> 
  </th> 
  <th> 
  <input type="button" value="CLEAR" id="cl_btn" onclick="clearTrs()" /> 
  </th> 
  <th> 
  <input type="button" value="GUESS" id="cl_btn"/> 
  </th> 
  </tr> 
 </thead> 
 <tbody> 
 </tbody> 
 </table> 
 </div> 
 </body> 
</html> 

構(gòu)造函數(shù)(偽構(gòu)造函數(shù))

考慮過,創(chuàng)建一個隱藏的tr,基于此tr執(zhí)行創(chuàng)建操作。為了不破壞HTML整體結(jié)構(gòu),決定通過js生成tr對象并append到頁面中。

為了在頁面加載完成后,再執(zhí)行dom操作,所以將<script>放在代碼下端</body>之前。

基于table中的tbody進(jìn)行增刪操作,可以先聲明此全局變量

var vTbody = document.getElementById('main-table').getElementsByTagName('tbody')[0]; 

創(chuàng)建對象,可以使用document.createElement方法。

以面向?qū)ο蟮姆绞竭M(jìn)行編程,先寫構(gòu)造函數(shù)(其實(shí)并不是標(biāo)準(zhǔn)的構(gòu)造函數(shù)格式),從最內(nèi)部的元素開始。

td中可能會有text和button等表單元素,所以先創(chuàng)建一個 input 的構(gòu)造函數(shù)function myInput(vId, vClass, vType, vValue, vParent){}

這里有一個兼容性問題,就是IE內(nèi)核不支持setAttribute(class, value),需要使用setAttribute(className, value),所以為了解決兼容問題,可以通過

setAttribute(class, value) for FF、Chrome..

setAttribute(className, value) for IE

這里采用的是另一種方式 .className,代碼如下:

function myInput(vId, vClass, vType, vValue, vParent) { 
 var vInput = document.createElement('input'); 
 if(vId) { 
 vInput.setAttribute('id', vId); 
 } 
 vInput.setAttribute('type', vType); 
 vInput.setAttribute('value', vValue); 
 vInput.className = vClass; 
 if(vParent) { 
 vParent.appendChild(vInput); 
 } 
} 

然后是td對象和tr對象的構(gòu)造函數(shù),大同小異,代碼如下

function myTd(vId, vClass, vChild, vParent) { 
 var vTd = document.createElement('td'); 
 if(vId){ 
 vTd.setAttribute('id', vId); 
 } 
 vTd.className = vClass; 
 if(vChild) { 
 vTd.appendChild(vChild); 
 } 
 if(vParent) { 
 vParent.appendChild(vTd); 
 } 
 return vTd; 
} 
function myTr(vId, vClass, vChild, vParent) { 
 var vTr = document.createElement('tr'); 
 if(vId){ 
 vTr.setAttribute('id', vId); 
 } 
 vTr.className = vClass; 
 if(vChild) { 
 vTr.appendChild(vChild); 
 } 
 if(vParent) { 
 vParent.appendChild(vTr); 
 } 
 return vTr; 
} 

新建行方法createTr()

構(gòu)造函數(shù)完成之后,完善createTr()方法。

預(yù)想的tr結(jié)構(gòu)為 序號,文本框,操作按鈕。

依次創(chuàng)建相關(guān)對象。序號列需要動態(tài)刷新,所以先設(shè)定class名稱,通過方法執(zhí)行排序操作。

function createTr() { 
 var vTr = new myTr(null, null, null, vTbody); 
 //序列td 
 var vTdSeq = new myTd(null, 'seq', null, vTr); 
 //文本框td 
 var vTdText = new myTd(null, null, null, vTr); 
 var vInputText = new myInput(null, 'td-inp-txt', 'text', '', vTdText); 
 //操作按鈕td 
 var vTdBtn = new myTd(null, null, null, vTr); 
 var vInputBtnCp = new myInput(null, 'td-inp-btn-cp', 'button', 'COPY', vTdBtn); 
 var vInputBtnDel = new myInput(null, 'td-inp-btn-del', 'button', 'DELETE', vTdBtn); 
} 

排序方法reSequence()

創(chuàng)建一個動態(tài)排序方法reSequence() ,有一個兼容性問題 innerText在火狐下無效果,所以使用innerHTML。代碼如下

function reSequence() { 
 var vObj = vTbody.getElementsByClassName('seq'); 
 for (var i=0, len=vObj.length; i<len; i++) { 
 vObj[i].innerHTML = i+1; 
 } 
} 

有一個兼容性問題,IE8及以下不支持getElementsByClassName()方法,網(wǎng)上找到了解決方案

if(!document.getElementsByClassName){ 
 document.getElementsByClassName = function(className, element){ 
 var children = (element || document).getElementsByTagName('*'); 
 var elements = new Array(); 
 for (var i=0; i<children.length; i++){ 
 var child = children[i]; 
 var classNames = child.className.split(' '); 
 for (var j=0; j<classNames.length; j++){ 
 if (classNames[j] == className){ 
  elements.push(child); 
  break; 
 } 
 } 
 } 
 return elements; 
 }; 
} 

試圖在Object或者是HTMLTableSectionElement的原型上增加此方法,如

HTMLTableSectionElement.prototype.getElementsByClassName = function(){} 

可惜沒有實(shí)現(xiàn)。

修改后的代碼為

function reSequence() { 
 var vObj = vTbody.getElementsByClassName == null?document.getElementsByClassName('seq', vTbody):vTbody.getElementsByClassName('seq'); 
 for (var i=0, len=vObj.length; i<len; i++) { 
 vObj[i].innerHTML = i+1; 
 } 
} 

除了排序外,還需其他操作,所以我們創(chuàng)建一個init()方法,集中管理reSequence()這些方法,在createTr()方法的結(jié)尾調(diào)用init()方法。

清空行方法clearTrs()

移除/銷毀某個dom對象,首先想到的是remove()方法,不幸的是,存在IE瀏覽器兼容問題,因此,采用了一個更簡便的方式,對dom對象執(zhí)行innerHTML="",代碼如下

function clearTrs() { 
 vTbody.innerHTML = ''; 
} 

IE8報錯,'未知的運(yùn)行錯誤'。查了以下,因?yàn)閕e8的table.innerHTML是只讀屬性,妹的!再改:

function clearTrs() { 
 while(vTbody.rows.length >0) { 
 vTbody.deleteRow(); 
 } 
} 

刪除行方法addBtnDelsListener()

接下來,給DELETE按鈕綁定刪除當(dāng)前行的方法。

為了解決兼容性問題,網(wǎng)上給出的方法是針對不同瀏覽器(IE、非IE)分別使用addEventListener、attachEvent方法,

我采用的是另一種解決方案:

obj.onclick = function(){};

匿名函數(shù)的方法體,吸取了上面clearTrs()方法的經(jīng)驗(yàn)教訓(xùn),直接采用deleteRow(index)方法。

有一點(diǎn)需要注意thisTr.rowIndex獲取的行數(shù),比當(dāng)前行要大2,因?yàn)閠head中還有兩行。所以當(dāng)前的索引數(shù)=thisTr.rowIndex-vThead.rows.length

代碼如下:

function addBtnDelsListener() { 
 var vBtnDels = vTbody.getElementsByClassName == null?document.getElementsByClassName('td-inp-btn-del', vTbody):vTbody.getElementsByClassName('td-inp-btn-del'); 
 for (var i=0, len=vBtnDels.length; i<len; i++) { 
 vBtnDels[i].onclick = function() { 
 var vTr = this.parentElement.parentElement; 
 vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName('thead')[0].rows.length); 
 reSequence(); 
 }; 
 } 
} 

執(zhí)行完刪除操作后,通過reSequence()方法重新排序。

同時將addBtnDelsListener()方法加入到init()方法中。

復(fù)制行方法addBtnCpsListener()

再來看一下COPY按鈕,添加事件監(jiān)聽的方式同上。

如果innerHTML不是只讀的話,可以createElement一個tr元素 然后newTr.innerHTML=thisTr.innerHTML,

為了兼容性,必須做些改變。

其實(shí)可以將復(fù)制看做是新建,唯一的不同在于新建行的文本輸入框的內(nèi)容要等同于被復(fù)制行。

這就簡單了。我可以先調(diào)用createTr()方法,再將最后一個元素lastChild中的文本框的value等于被復(fù)制行。

思路有了,代碼如下:

function addBtnCpsListener() { 
 var vBtnCps = vTbody.getElementsByClassName == null?document.getElementsByClassName('td-inp-btn-cp', vTbody):vTbody.getElementsByClassName('td-inp-btn-cp'); 
 for (var i=0, len=vBtnCps.length; i<len; i++) { 
 vBtnCps[i].onclick = function() { 
 createTr(); 
 var vNewTr = vTbody.lastChild; 
 var vTr = this.parentElement.parentElement; 
 vNewTr.getElementsByClassName == null?document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = document.getElementsByClassName('td-inp-txt', vTr)[0].value:vNewTr.getElementsByClassName('td-inp-txt')[0].value = vTr.getElementsByClassName('td-inp-txt')[0].value; 
 } 
 } 
} 

優(yōu)化修改

進(jìn)行一些優(yōu)化修改工作:

var elements = new Array();

修改為:var elements = [];

原因:數(shù)組用[]更好

addBtnDelsListener方法中的vBtnDels[i].onclick = function() {

修改為:vBtnDels[i].onclick = delTr;

外部新創(chuàng)建一個函數(shù)

function delTr() { 
 var vTr = this.parentElement.parentElement; 
 vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName('thead')[0].rows.length); 
 reSequence(); 
 } 

原因:Don't make functions within a loop.

同理,將addBtnCpsListener中的vBtnCps[i].onclick = function() {

修改為:vBtnCps[i].onclick = copyTr;

外部新創(chuàng)建一個函數(shù)

<pre code_snippet_id="139791" snippet_file_name="blog_20140103_15_6784659" name="code" class="javascript"> function copyTr() { 
 createTr(); 
 var vNewTr = vTbody.lastChild; 
 var vTr = this.parentElement.parentElement; 
 vNewTr.getElementsByClassName === null? 
 document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = 
 document.getElementsByClassName('td-inp-txt', vTr)[0].value: 
 vNewTr.getElementsByClassName('td-inp-txt')[0].value = 
 vTr.getElementsByClassName('td-inp-txt')[0].value; 
 }</pre> 
<pre></pre> 
<pre></pre> 

copyTr()方法中的?:格式修改為if else函數(shù)。

修改為:

function copyTr() { 
 createTr(); 
 var vNewTr = vTbody.lastChild; 
 var vTr = this.parentElement.parentElement; 
 if(vNewTr.getElementsByClassName) { 
 vNewTr.getElementsByClassName('td-inp-txt')[0].value = 
 vTr.getElementsByClassName('td-inp-txt')[0].value; 
 } else { 
 document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = 
 document.getElementsByClassName('td-inp-txt', vTr)[0].value; 
 } 
} 

原因:?:預(yù)期返回值應(yīng)該是一個變量or函數(shù),而不應(yīng)該是一個表達(dá)式操作。

有一點(diǎn)需要注意:js最佳實(shí)現(xiàn)經(jīng)常看到要使用===替換==。但是本示例中的==null,如果替換成===null會在ie8一下版本中出現(xiàn)問題。

完整代碼

至此,一個完全基于原生JavaScript,并且兼容至IE6的table增刪完成了。

還是想吐槽一下,如果不兼容IE10以下的版本,可以節(jié)省50%的代碼。如果使用jQuery,又可以節(jié)省50%的代碼。對于實(shí)用主義的我而言,這一過程備受煎熬。不過還是從中有所收益的(違心。。)

以下為完整代碼:

<!DOCTYPE HTML> 
<html> 
 <head> 
 <title>table</title> 
 <meta charset='utf-8' /> 
 <style type="text/css"> 
 table.base{ 
 border-collapse:collapse; 
 text-align: center; 
 border: 1px solid black; 
 } 
 table, tr, td, th{ 
 border: 1px solid black; 
 } 
 </style> 
 </head> 
 <body> 
 <div id="main-content"> 
 <table id="main-table" class="base"> 
 <thead> 
  <tr> 
  <th colspan="3">This is a table for operations by javascript</th> 
  </tr> 
  <tr> 
  <th> 
  <input type="button" value="CREATE" id="cp_btn" onclick="createTr()" /> 
  </th> 
  <th> 
  <input type="button" value="CLEAR" id="cl_btn" onclick="clearTrs()" /> 
  </th> 
  <th> 
  <input type="button" value="GUESS" id="cl_btn"/> 
  </th> 
  </tr> 
 </thead> 
 <tbody> 
 </tbody> 
 </table> 
 </div> 
 <script type="text/javascript"> 
 if(!document.getElementsByClassName){ 
 document.getElementsByClassName = function(className, element){ 
  var children = (element || document).getElementsByTagName('*'); 
  var elements = []; 
  for (var i=0; i<children.length; i++){ 
  var child = children[i]; 
  var classNames = child.className.split(' '); 
  for (var j=0; j<classNames.length; j++){ 
  if (classNames[j] == className){ 
  elements.push(child); 
  break; 
  } 
  } 
  } 
  return elements; 
 }; 
 } 
 var vTbody = document.getElementById('main-table').getElementsByTagName('tbody')[0]; 
 function myInput(vId, vClass, vType, vValue, vParent) { 
 var vInput = document.createElement('input'); 
 if(vId) { 
  vInput.setAttribute('id', vId); 
 } 
 vInput.setAttribute('type', vType); 
 vInput.setAttribute('value', vValue); 
 vInput.className = vClass; 
 if(vParent) { 
  vParent.appendChild(vInput); 
 } 
 return vInput; 
 } 
 function myTd(vId, vClass, vChild, vParent) { 
 var vTd = document.createElement('td'); 
 if(vId){ 
  vTd.setAttribute('id', vId); 
 } 
 vTd.className = vClass; 
 if(vChild) { 
  vTd.appendChild(vChild); 
 } 
 if(vParent) { 
  vParent.appendChild(vTd); 
 } 
 return vTd; 
 } 
 function myTr(vId, vClass, vChild, vParent) { 
 var vTr = document.createElement('tr'); 
 if(vId){ 
  vTr.setAttribute('id', vId); 
 } 
 vTr.className = vClass; 
 if(vChild) { 
  vTr.appendChild(vChild); 
 } 
 if(vParent) { 
  vParent.appendChild(vTr); 
 } 
 return vTr; 
 } 
 function createTr() { 
 var vTr = new myTr(null, null, null, vTbody); 
 //序列td 
 var vTdSeq = new myTd(null, 'seq', null, vTr); 
 //文本框td 
 var vTdText = new myTd(null, null, null, vTr); 
 var vInputText = new myInput(null, 'td-inp-txt', 'text', '', vTdText); 
 //操作按鈕td 
 var vTdBtn = new myTd(null, null, null, vTr); 
 var vInputBtnCp = new myInput(null, 'td-inp-btn-cp', 'button', 'COPY', vTdBtn); 
 var vInputBtnDel = new myInput(null, 'td-inp-btn-del', 'button', 'DELETE', vTdBtn); 
 init(); 
 } 
 function clearTrs() { 
 while(vTbody.rows.length >0) { 
  vTbody.deleteRow(); 
 } 
 } 
 function init(){ 
 reSequence(); 
 addBtnDelsListener(); 
 addBtnCpsListener(); 
 } 
 function reSequence() { 
 var vObj = vTbody.getElementsByClassName == null? 
document.getElementsByClassName('seq', vTbody): 
vTbody.getElementsByClassName('seq'); 
 for (var i=0, len=vObj.length; i<len; i++) { 
  vObj[i].innerHTML = i+1; 
 } 
 } 
 function addBtnDelsListener() { 
 var vBtnDels = vTbody.getElementsByClassName == null? 
document.getElementsByClassName('td-inp-btn-del', vTbody): 
vTbody.getElementsByClassName('td-inp-btn-del'); 
 for (var i=0, len=vBtnDels.length; i<len; i++) { 
  vBtnDels[i].onclick = delTr; 
 } 
 } 
 function delTr() { 
 var vTr = this.parentElement.parentElement; 
 vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName('thead')[0].rows.length); 
 reSequence(); 
 } 
 function addBtnCpsListener() { 
 var vBtnCps = vTbody.getElementsByClassNamenull == null? 
document.getElementsByClassName('td-inp-btn-cp', vTbody): 
vTbody.getElementsByClassName('td-inp-btn-cp'); 
for (var i=0, len=vBtnCps.length; i<len; i++) { 
  vBtnCps[i].onclick = copyTr; 
 } 
 } 
 function copyTr() { 
 createTr(); 
 var vNewTr = vTbody.lastChild; 
 var vTr = this.parentElement.parentElement; 
 if(vNewTr.getElementsByClassName) { 
  vNewTr.getElementsByClassName('td-inp-txt')[0].value = 
  vTr.getElementsByClassName('td-inp-txt')[0].value; 
 } else { 
  document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = 
  document.getElementsByClassName('td-inp-txt', vTr)[0].value; 
 } 
 } 
 </script> 
 </body> 
</html> 

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

最新評論