Heim  >  Artikel  >  Web-Frontend  >  Reines natives JS realisiert das Hinzufügen und Löschen von Tabellen

Reines natives JS realisiert das Hinzufügen und Löschen von Tabellen

高洛峰
高洛峰Original
2017-01-07 10:12:371234Durchsuche

Der Firmenpraktikant fragte mich nach dem Hinzufügen und Löschen von Tabellen und es war mit jQuery sehr einfach zu implementieren. Er fragte mich auch, wie ich es ohne jQuery und nur mit js implementieren könne.

Angesichts dieser Situation ist mein üblicher Ansatz „nicht verstehen, sondern unterstützen“.

JQuery wird häufig verwendet und die Leute sind zu faul, aber ich denke, die Schwierigkeit liegt in der IE-Kompatibilität. . .

Wenn Sie nur nach dem Code suchen möchten, können Sie den Analysevorgang überspringen. Der vollständige Code ist am Ende des Artikels angehängt.

Das Folgende ist der Codierungsprozess:

HTML-Strukturcode

Eine grundlegende Tabellenstruktur mit einigen hinzugefügten einfachen Stilen. Drei Schaltflächen entsprechen „Erstellen“, „Löschen“ und „Reserviert“.

<!DOCTYPE HTML> 
<html> 
 <head> 
  <title>table</title> 
  <meta charset=&#39;utf-8&#39; /> 
  <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>

Konstruktor (Pseudokonstruktor)

In Betracht gezogen, erstellen Sie ein verstecktes Tr und führen Sie den Erstellungsvorgang basierend auf diesem Tr aus. Um die Gesamtstruktur von HTML nicht zu zerstören, wurde beschlossen, das tr-Objekt über js zu generieren und an die Seite anzuhängen.

Um DOM-Operationen nach dem Laden der Seite auszuführen, platzieren Sie 3f1c4e4b6b16bbbd69b2ee476dc4f83a am Ende des Codes vor 36cc49f0c466276486e50c850b7e4956.

Um Additions- und Löschvorgänge basierend auf tbody in der Tabelle durchzuführen, können Sie zunächst diese globale Variable deklarieren

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

Um ein Objekt zu erstellen, können Sie die Methode document.createElement verwenden.

Objektorientiert programmieren, zuerst den Konstruktor schreiben (eigentlich handelt es sich nicht um ein Standardkonstruktorformat), beginnend mit dem innersten Element.

Es kann Formularelemente wie Text und Schaltfläche in td geben, also erstellen Sie zunächst eine Eingabekonstruktorfunktion myInput(vId, vClass, vType, vValue, vParent){}

Hier ist eines Das Kompatibilitätsproblem besteht darin, dass der IE-Kernel setAttribute(class, value) nicht unterstützt und setAttribute(className, value) verwenden muss. Um das Kompatibilitätsproblem zu lösen, können Sie daher

setAttribute(class,) verwenden. value) für FF und Chrome.

setAttribute(className, value) für IE

Hier ist eine andere Möglichkeit .className, der Code lautet wie folgt:

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

Dann td Objekt und tr Der Konstruktor des Objekts ist ähnlich, der Code lautet wie folgt

function myTd(vId, vClass, vChild, vParent) { 
 var vTd = document.createElement(&#39;td&#39;); 
 if(vId){ 
  vTd.setAttribute(&#39;id&#39;, 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(&#39;tr&#39;); 
 if(vId){ 
  vTr.setAttribute(&#39;id&#39;, vId); 
 } 
 vTr.className = vClass; 
 if(vChild) { 
  vTr.appendChild(vChild); 
 } 
 if(vParent) { 
  vParent.appendChild(vTr); 
 } 
 return vTr; 
}

Neue Zeilenmethode createTr()

Verbessern Sie nach Abschluss des Konstruktors die Methode createTr() Verfahren.

Die erwartete Tr-Struktur besteht aus Seriennummer, Textfeld und Bedienschaltfläche.

Erstellen Sie verwandte Objekte nacheinander. Die Seriennummernspalte muss dynamisch aktualisiert werden. Legen Sie daher zunächst den Klassennamen fest und führen Sie den Sortiervorgang über die Methode durch.

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

Sortiermethode reSequence()

Erstellen Sie eine dynamische Sortiermethode reSequence(). Es gibt ein Kompatibilitätsproblem unter Firefox, daher wird innerHTML verwendet. Der Code lautet wie folgt:

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

Es gibt ein Kompatibilitätsproblem. IE8 und unten unterstützen die Methode getElementsByClassName() nicht. Ich habe online eine Lösung gefunden.

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

Ich habe versucht, die zu verwenden Prototyp von Object oder HTMLTableSectionElement Fügen Sie diese Methode hinzu, z. B.

HTMLTableSectionElement.prototype.getElementsByClassName = function(){}

Leider ist sie nicht implementiert.

Der geänderte Code ist

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

Zusätzlich zum Sortieren sind weitere Vorgänge erforderlich, daher erstellen wir in createTr() eine init()-Methode, um die reSequence()-Methoden zentral zu verwalten Die Methode init() wird am Ende der Methode aufgerufen.

Leerzeilenmethode „clearTrs()“ löschen

Um ein DOM-Objekt zu entfernen/zerstören, fällt mir als Erstes die Methode „remove()“ ein. Leider gibt es ein Kompatibilitätsproblem mit dem IE-Browser , also verwenden Sie eine einfachere Möglichkeit, innerHTML="" für das Dom-Objekt auszuführen. Der Code lautet wie folgt:

function clearTrs() { 
 vTbody.innerHTML = &#39;&#39;; 
}

IE8 meldet einen Fehler: „Unbekannter Ausführungsfehler“. Ich habe Folgendes überprüft, weil die table.innerHTML von IE8 ein schreibgeschütztes Attribut ist, verdammt! Erneut ändern:

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

Zeilenmethode löschen addBtnDelsListener()

Als nächstes binden Sie die Methode zum Löschen der aktuellen Zeile an die Schaltfläche DELETE.

Um das Kompatibilitätsproblem zu lösen, besteht die im Internet angegebene Methode darin, die Methoden addEventListener bzw. attachmentEvent für verschiedene Browser (IE, Nicht-IE) zu verwenden.

Ich verwende eine andere Lösung :

obj.onclick = function(){};

Der Methodenkörper der anonymen Funktion hat die Erfahrungen und Lehren aus der obigen Methode clearTrs() gelernt und verwendet direkt den deleteRow(index ) Methode.

Zu beachten ist, dass die Anzahl der von thisTr.rowIndex erhaltenen Zeilen um 2 größer ist als die aktuelle Zeile, da sich im Kopf zwei weitere Zeilen befinden. Die aktuelle Anzahl der Indizes ist also = thisTr.rowIndex-vThead.rows.length

Der Code lautet wie folgt:

function addBtnDelsListener() { 
 var vBtnDels = vTbody.getElementsByClassName == null?document.getElementsByClassName(&#39;td-inp-btn-del&#39;, vTbody):vTbody.getElementsByClassName(&#39;td-inp-btn-del&#39;); 
 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(&#39;thead&#39;)[0].rows.length); 
   reSequence(); 
  }; 
 } 
}

Nachdem Sie den Löschvorgang ausgeführt haben, ordnen Sie ihn mithilfe der reSequence()-Methode neu an .

Fügen Sie gleichzeitig die Methode addBtnDelsListener() zur Methode init() hinzu.

Zeilenmethode addBtnCpsListener() kopieren

Sehen Sie sich noch einmal die Schaltfläche KOPIEREN an. Die Methode zum Hinzufügen von Ereignis-Listenern ist dieselbe wie oben.

Wenn innerHTML nicht schreibgeschützt ist, können Sie Element ein tr-Element und dann newTr.innerHTML=thisTr.innerHTML erstellen.

Aus Kompatibilitätsgründen müssen einige Änderungen vorgenommen werden.

Tatsächlich kann das Kopieren als Erstellen einer neuen Zeile betrachtet werden. Der einzige Unterschied besteht darin, dass der Inhalt des Texteingabefelds der neuen Zeile mit dem Inhalt der kopierten Zeile übereinstimmen muss.

Das ist ganz einfach. Ich kann zuerst die Methode createTr() aufrufen und dann den Wert des Textfelds im letzten Element lastChild so festlegen, dass er der kopierten Zeile entspricht.

Ich habe die Idee, der Code lautet wie folgt:

function addBtnCpsListener() { 
 var vBtnCps = vTbody.getElementsByClassName == null?document.getElementsByClassName(&#39;td-inp-btn-cp&#39;, vTbody):vTbody.getElementsByClassName(&#39;td-inp-btn-cp&#39;); 
 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(&#39;td-inp-txt&#39;, vNewTr)[0].value = document.getElementsByClassName(&#39;td-inp-txt&#39;, vTr)[0].value:vNewTr.getElementsByClassName(&#39;td-inp-txt&#39;)[0].value = vTr.getElementsByClassName(&#39;td-inp-txt&#39;)[0].value; 
  } 
 } 
}

Optimierungsänderungen

Führen Sie einige Optimierungsänderungen durch:

var elements = neues Array ();

geändert zu: var elements = [];

Grund: Es ist besser, [] für Arrays zu verwenden

vBtnDels[i].onclick = Funktion ändern () in der addBtnDelsListener-Methode {

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

外部新创建一个函数

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

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

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

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

外部新创建一个函数

<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(&#39;td-inp-txt&#39;, vNewTr)[0].value = 
    document.getElementsByClassName(&#39;td-inp-txt&#39;, vTr)[0].value: 
    vNewTr.getElementsByClassName(&#39;td-inp-txt&#39;)[0].value = 
    vTr.getElementsByClassName(&#39;td-inp-txt&#39;)[0].value; 
   }
 

将copyTr()方法中的?:格式修改为if else函数。

修改为:

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

原因:?:预期返回值应该是一个变量or函数,而不应该是一个表达式操作。

有一点需要注意:js最佳实现经常看到要使用===替换==。但是本示例中的==null,如果替换成===null会在ie8一下版本中出现问题。

完整代码

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

还是想吐槽一下,如果不兼容IE10以下的版本,可以节省50%的代码。如果使用jQuery,又可以节省50%的代码。对于实用主义的我而言,这一过程备受煎熬。不过还是从中有所收益的(违心。。)

以下为完整代码:

 
 
  
  table 
   
   
  
  
  
This is a table for operations by javascript

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持PHP中文网!

更多纯原生js实现table表格的增删相关文章请关注PHP中文网!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn