Home > Web Front-end > JS Tutorial > body text

Pure native js realizes the addition and deletion of tables

高洛峰
Release: 2017-01-07 10:12:37
Original
1268 people have browsed it

The company intern asked me about the addition and deletion operations of the table, which was easily implemented using jQuery. He also asked me how to implement it without using jQuery and only using js.

Faced with this situation, my usual approach is 'don't understand, but support'.

JQuery is used a lot, and people are too lazy, but I still use js to implement this operation. I think the difficulty lies in IE compatibility. . .

If you just want to find the code, you can skip the analysis process. The complete code is attached at the bottom of the article.

The following is the coding process:

HTML structure code

A basic table structure, with some simple styles added, three buttons corresponding to create, clear, and a Reserved.

<!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>
Copy after login

Constructor (pseudo constructor)

Considered, create a hidden tr, and perform the creation operation based on this tr. In order not to destroy the overall structure of HTML, it was decided to generate the tr object through js and append it to the page.

In order to perform DOM operations after the page is loaded, place <script> before </body> at the bottom of the code. </p><p>To perform addition and deletion operations based on tbody in the table, you can first declare this global variable</p><p>var vTbody = document.getElementById('main-table').getElementsByTagName('tbody')[0] ; </p><p>To create an object, you can use the document.createElement method. </p><p>Programming in an object-oriented way, first write the constructor (in fact, it is not a standard constructor format), starting from the innermost element. </p><p>There may be form elements such as text and button in td, so first create an input constructor function myInput(vId, vClass, vType, vValue, vParent){}</p><p>Here is one The compatibility problem is that the IE kernel does not support setAttribute(class, value) and needs to use setAttribute(className, value). Therefore, in order to solve the compatibility problem, you can use </p><p>setAttribute(class, value) for FF and Chrome. .</p><p>setAttribute(className, value) for IE</p><p>Here is another way.className, the code is as follows:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function myInput(vId, vClass, vType, vValue, vParent) { var vInput = document.createElement(&amp;#39;input&amp;#39;); if(vId) { vInput.setAttribute(&amp;#39;id&amp;#39;, vId); } vInput.setAttribute(&amp;#39;type&amp;#39;, vType); vInput.setAttribute(&amp;#39;value&amp;#39;, vValue); vInput.className = vClass; if(vParent) { vParent.appendChild(vInput); } }</pre><div class="contentsignin">Copy after login</div></div><p>Then the td object and tr object The constructor is similar, the code is as follows </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function myTd(vId, vClass, vChild, vParent) { var vTd = document.createElement(&amp;#39;td&amp;#39;); if(vId){ vTd.setAttribute(&amp;#39;id&amp;#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(&amp;#39;tr&amp;#39;); if(vId){ vTr.setAttribute(&amp;#39;id&amp;#39;, vId); } vTr.className = vClass; if(vChild) { vTr.appendChild(vChild); } if(vParent) { vParent.appendChild(vTr); } return vTr; }</pre><div class="contentsignin">Copy after login</div></div><p>New row method createTr()</p><p>After the constructor is completed, improve the createTr() method. </p><p>The expected tr structure is serial number, text box, and operation button. </p><p>Create related objects in sequence. The serial number column needs to be refreshed dynamically, so first set the class name and perform the sorting operation through the method. </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function createTr() { var vTr = new myTr(null, null, null, vTbody); //序列td var vTdSeq = new myTd(null, &amp;#39;seq&amp;#39;, null, vTr); //文本框td var vTdText = new myTd(null, null, null, vTr); var vInputText = new myInput(null, &amp;#39;td-inp-txt&amp;#39;, &amp;#39;text&amp;#39;, &amp;#39;&amp;#39;, vTdText); //操作按钮td var vTdBtn = new myTd(null, null, null, vTr); var vInputBtnCp = new myInput(null, &amp;#39;td-inp-btn-cp&amp;#39;, &amp;#39;button&amp;#39;, &amp;#39;COPY&amp;#39;, vTdBtn); var vInputBtnDel = new myInput(null, &amp;#39;td-inp-btn-del&amp;#39;, &amp;#39;button&amp;#39;, &amp;#39;DELETE&amp;#39;, vTdBtn); }</pre><div class="contentsignin">Copy after login</div></div><p>Sorting method reSequence()</p><p>Create a dynamic sorting method reSequence(). There is a compatibility issue. innerText has no effect under Firefox, so innerHTML is used. The code is as follows </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false">function reSequence() { var vObj = vTbody.getElementsByClassName(&amp;#39;seq&amp;#39;); for (var i=0, len=vObj.length; i&lt;len; i++) { vObj[i].innerHTML = i+1; } }</pre><div class="contentsignin">Copy after login</div></div><p> There is a compatibility issue. IE8 and below do not support the getElementsByClassName() method. I found a solution online </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">if(!document.getElementsByClassName){ document.getElementsByClassName = function(className, element){ var children = (element || document).getElementsByTagName(&amp;#39;*&amp;#39;); var elements = new Array(); for (var i=0; i&lt;children.length; i++){ var child = children[i]; var classNames = child.className.split(&amp;#39; &amp;#39;); for (var j=0; j&lt;classNames.length; j++){ if (classNames[j] == className){ elements.push(child); break; } } } return elements; }; }</pre><div class="contentsignin">Copy after login</div></div><p> Trying to add this method to the prototype of Object or HTMLTableSectionElement. Such as </p><p>HTMLTableSectionElement.prototype.getElementsByClassName = function(){} </p><p>Unfortunately, it is not implemented. </p><p>The modified code is </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function reSequence() { var vObj = vTbody.getElementsByClassName == null?document.getElementsByClassName(&amp;#39;seq&amp;#39;, vTbody):vTbody.getElementsByClassName(&amp;#39;seq&amp;#39;); for (var i=0, len=vObj.length; i&lt;len; i++) { vObj[i].innerHTML = i+1; } }</pre><div class="contentsignin">Copy after login</div></div><p>In addition to sorting, other operations are required, so we create an init() method to centrally manage the reSequence() methods. In the createTr() method At the end, the init() method is called. </p><p>Clear row method clearTrs()</p><p>To remove/destroy a DOM object, the first thing that comes to mind is the remove() method. Unfortunately, there are IE browser compatibility issues, so use A simpler way is to execute innerHTML="" on the dom object. The code is as follows </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function clearTrs() { vTbody.innerHTML = &amp;#39;&amp;#39;; }</pre><div class="contentsignin">Copy after login</div></div><p>IE8 reports an error, 'Unknown running error'. I checked the following, because the table.innerHTML of IE8 is a read-only attribute, damn it! Change again: </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function clearTrs() { while(vTbody.rows.length &gt;0) { vTbody.deleteRow(); } }</pre><div class="contentsignin">Copy after login</div></div><p>Delete row method addBtnDelsListener()</p><p>Next, bind the method of deleting the current row to the DELETE button. </p><p>In order to solve the compatibility problem, the method given on the Internet is to use the addEventListener and attachEvent methods for different browsers (IE, non-IE) respectively. </p><p>I use another solution :</p><p>obj.onclick = function(){};</p><p>The method body of the anonymous function has learned the lessons learned from the clearTrs() method above and directly uses the deleteRow(index) method. </p><p>One thing to note is that the number of rows obtained by thisTr.rowIndex is 2 greater than the current row, because there are two rows in thead. So the current number of indexes = thisTr.rowIndex-vThead.rows.length</p><p>The code is as follows:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function addBtnDelsListener() { var vBtnDels = vTbody.getElementsByClassName == null?document.getElementsByClassName(&amp;#39;td-inp-btn-del&amp;#39;, vTbody):vTbody.getElementsByClassName(&amp;#39;td-inp-btn-del&amp;#39;); for (var i=0, len=vBtnDels.length; i&lt;len; i++) { vBtnDels[i].onclick = function() { var vTr = this.parentElement.parentElement; vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName(&amp;#39;thead&amp;#39;)[0].rows.length); reSequence(); }; } }</pre><div class="contentsignin">Copy after login</div></div><p>After performing the deletion operation, reorder through the reSequence() method. </p><p>At the same time, add the addBtnDelsListener() method to the init() method. </p><p>Copy line method addBtnCpsListener()</p><p> Let’s look at the COPY button again. The method of adding event listeners is the same as above. </p><p>If innerHTML is not read-only, you can createElement a tr element and then newTr.innerHTML=thisTr.innerHTML, </p><p>For compatibility, some changes must be made. </p><p>In fact, copying can be regarded as creating a new one. The only difference is that the content of the text input box of the new row must be equal to the copied row. </p><p>That’s easy. I can call the createTr() method first, and then set the value of the text box in the last element lastChild to be equal to the copied row. </p><p>The idea is there, the code is as follows: </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function addBtnCpsListener() { var vBtnCps = vTbody.getElementsByClassName == null?document.getElementsByClassName(&amp;#39;td-inp-btn-cp&amp;#39;, vTbody):vTbody.getElementsByClassName(&amp;#39;td-inp-btn-cp&amp;#39;); for (var i=0, len=vBtnCps.length; i&lt;len; i++) { vBtnCps[i].onclick = function() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; vNewTr.getElementsByClassName == null?document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vNewTr)[0].value = document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vTr)[0].value:vNewTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value = vTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value; } } }</pre><div class="contentsignin">Copy after login</div></div><p>Optimization and modification</p><p>Perform some optimization and modification work:</p><p>var elements = new Array();</p><p>Modify to: var elements = [];</p><p>Reason: It is better to use [] for the array</p><p>Change vBtnDels[i].onclick = function() {# in the addBtnDelsListener method ##<p>修改为:vBtnDels[i].onclick = delTr;</p><p>外部新创建一个函数</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function delTr() { var vTr = this.parentElement.parentElement; vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName(&amp;#39;thead&amp;#39;)[0].rows.length); reSequence(); }</pre><div class="contentsignin">Copy after login</div></div><p>原因:Don&#39;t make functions within a loop.</p><p>同理,将addBtnCpsListener中的vBtnCps[i].onclick = function() {</p><p>修改为:vBtnCps[i].onclick = copyTr;</p><p>外部新创建一个函数</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">&lt;pre code_snippet_id=&quot;139791&quot; snippet_file_name=&quot;blog_20140103_15_6784659&quot; name=&quot;code&quot; class=&quot;javascript&quot;&gt; function copyTr() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; vNewTr.getElementsByClassName === null? document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vNewTr)[0].value = document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vTr)[0].value: vNewTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value = vTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value; }</pre> <pre class="brush:php;toolbar:false"></pre> <pre class="brush:php;toolbar:false"></pre></pre><div class="contentsignin">Copy after login</div></div><p>将copyTr()方法中的?:格式修改为if else函数。</p><p>修改为:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">function copyTr() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; if(vNewTr.getElementsByClassName) { vNewTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value = vTr.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;)[0].value; } else { document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vNewTr)[0].value = document.getElementsByClassName(&amp;#39;td-inp-txt&amp;#39;, vTr)[0].value; } }</pre><div class="contentsignin">Copy after login</div></div><p>原因:?:预期返回值应该是一个变量or函数,而不应该是一个表达式操作。</p><p>有一点需要注意:js最佳实现经常看到要使用===替换==。但是本示例中的==null,如果替换成===null会在ie8一下版本中出现问题。</p><p>完整代码</p><p>至此,一个完全基于原生JavaScript,并且兼容至IE6的table增删完成了。</p><p>还是想吐槽一下,如果不兼容IE10以下的版本,可以节省50%的代码。如果使用jQuery,又可以节省50%的代码。对于实用主义的我而言,这一过程备受煎熬。不过还是从中有所收益的(违心。。)</p><p>以下为完整代码:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false"><!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> <script type="text/javascript"> if(!document.getElementsByClassName){ document.getElementsByClassName = function(className, element){ var children = (element || document).getElementsByTagName(&#39;*&#39;); var elements = []; 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; }; } var vTbody = document.getElementById(&#39;main-table&#39;).getElementsByTagName(&#39;tbody&#39;)[0]; 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); } return vInput; } 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; } 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); init(); } function clearTrs() { while(vTbody.rows.length >0) { vTbody.deleteRow(); } } function init(){ reSequence(); addBtnDelsListener(); addBtnCpsListener(); } 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; } } 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 = delTr; } } function delTr() { var vTr = this.parentElement.parentElement; vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName(&amp;#39;thead&amp;#39;)[0].rows.length); reSequence(); } function addBtnCpsListener() { var vBtnCps = vTbody.getElementsByClassNamenull == 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 = copyTr; } } 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; } } </script>

Copy after login

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

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


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!