순수 네이티브 js는 테이블 추가 및 삭제를 실현합니다.

高洛峰
풀어 주다: 2017-01-07 10:12:37
원래의
1281명이 탐색했습니다.

회사 인턴이 테이블 추가 및 삭제에 대해 문의했는데 jQuery를 이용해서 구현하는 방법이 아주 간단했습니다. 그는 또한 jQuery를 사용하지 않고 js만 사용하여 구현하는 방법을 물었습니다.

이러한 상황에 직면했을 때 제가 평소 접근하는 방식은 '이해하지 말고 지지'입니다.

JQuery를 많이 사용하고 사람들이 너무 게으른데, 이 작업을 수행하기 위해 여전히 js를 사용하는 것은 IE 호환성에 있는 것 같습니다. . .

코드만 찾고 싶으신 분은 분석 과정을 건너뛰셔도 됩니다. 전체 코드는 글 하단에 첨부되어 있습니다.

코딩 과정은 다음과 같습니다.

HTML 구조 코드

몇 가지 간단한 스타일이 추가되고 생성, 삭제 및 예약에 해당하는 세 개의 버튼이 있는 기본 테이블 구조입니다. .

<!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>
로그인 후 복사

생성자(의사 생성자)

고려하여 숨겨진 tr을 생성하고, 이 tr을 기반으로 생성 작업을 수행합니다. HTML의 전체 구조를 파괴하지 않기 위해 js를 통해 tr 객체를 생성하여 페이지에 추가하기로 결정했습니다.

페이지가 로드된 후 DOM 작업을 수행하려면 코드 하단의 앞에 <script>를 배치하세요. </p><p>테이블의 tbody를 기반으로 추가 및 삭제 작업을 수행하려면 먼저 이 전역 변수를 선언하면 됩니다. </p><p>var vTbody = document.getElementById('main-table').getElementsByTagName('tbody ')[0] ; </p><p>객체를 생성하려면 document.createElement 메서드를 사용할 수 있습니다. </p><p>객체 지향 방식으로 프로그래밍하면 가장 안쪽 요소부터 시작하여 생성자를 먼저 작성합니다(실제로는 표준 생성자 형식이 아닙니다). </p><p>td에는 텍스트, 버튼과 같은 양식 요소가 있을 수 있으므로 먼저 입력 생성자 함수 myInput(vId, vClass, vType, vValue, vParent)를 만듭니다.{}</p><p>다음은 하나입니다. 호환성 문제는 IE 커널이 setAttribute(class, value)를 지원하지 않으며 setAttribute(className, value)를 사용해야 한다는 것입니다. 따라서 호환성 문제를 해결하려면 </p><p>setAttribute(class, FF 및 Chrome의 경우 .</p><p>IE의 경우 setAttribute(className, value)</p><p>여기에 .className의 또 다른 방법이 있습니다. 코드는 다음과 같습니다. </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">로그인 후 복사</div></div><p> 그런 다음 td 객체와 tr 객체의 생성자는 유사하며 코드는 다음과 같습니다 </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">로그인 후 복사</div></div><p>새 행 메서드 createTr()</p><p>생성자가 완료된 후 createTr()을 개선합니다. 방법. </p><p>예상되는 tr 구조는 일련번호, 텍스트 상자, 작업 버튼입니다. </p><p>관련 개체를 순차적으로 생성합니다. 일련번호 열은 동적으로 새로 고쳐야 하므로 먼저 클래스 이름을 설정하고 메소드를 통해 정렬 작업을 수행합니다. </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">로그인 후 복사</div></div><p>정렬 방법 reSequence()</p><p>동적 정렬 방법 reSequence()를 만듭니다. Firefox에서는 innerText가 효과가 없으므로 innerHTML이 사용됩니다. 코드는 다음과 같습니다. </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">로그인 후 복사</div></div><p>IE8 이하에서는 getElementsByClassName() 메소드를 지원하지 않습니다. 온라인에서 해결책을 찾았습니다</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">로그인 후 복사</div></div><p> Object 또는 HTMLTableSectionElement의 프로토타입에 </p><p>HTMLTableSectionElement.prototype.getElementsByClassName = function(){} </p><p>과 같은 이 메서드를 추가합니다. 안타깝게도 구현되지 않았습니다. </p><p>수정된 코드는 </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">로그인 후 복사</div></div><p>정렬 외에 다른 작업이 필요하므로 createTr()에 reSequence() 메소드를 중앙에서 관리하기 위한 init() 메소드를 생성합니다. init() 메서드는 메서드 끝에서 호출됩니다. </p><p>빈 줄 지우기 메소드clearTrs()</p><p>DOM 객체를 제거/파괴하려면 가장 먼저 떠오르는 것은 Remove() 메소드입니다. 안타깝게도 IE 브라우저 호환성 문제가 있습니다. 이므로 더 간단한 방법은 dom 개체에서 innerHTML=""을 실행하는 것입니다. 코드는 다음과 같습니다. </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">로그인 후 복사</div></div><p>IE8에서는 '알 수 없는 실행 오류'라는 오류를 보고합니다. IE8의 table.innerHTML은 읽기 전용 속성이기 때문에 다음을 확인했습니다. 젠장! 다시 변경: </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">로그인 후 복사</div></div><p>행 삭제 메소드 addBtnDelsListener()</p><p>다음으로 현재 행을 삭제하는 메소드를 DELETE 버튼에 바인딩합니다. </p><p>호환성 문제를 해결하기 위해 인터넷에서 제시하는 방법은 브라우저별로(IE, non-IE) addEventListener, attachmentEvent 메소드를 각각 사용하는 것입니다. </p><p>다른 솔루션을 사용합니다. :</p><p>obj.onclick = function(){};</p><p>익명 함수의 메서드 본문은 위의clearTrs() 메서드에서 경험과 교훈을 얻었으며 deleteRow(index)를 직접 사용합니다. ) 방법. </p><p>한 가지 주의할 점은 thead에 행이 2개 더 있기 때문에 thisTr.rowIndex에서 얻은 행 수가 현재 행보다 2개 더 많다는 것입니다. 따라서 현재 인덱스 수 = thisTr.rowIndex-vThead.rows.length</p><p>코드는 다음과 같습니다.</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">로그인 후 복사</div></div><p>삭제 작업을 수행한 후 reSequence() 메서드를 통해 재정렬합니다. . </p><p>동시에 init() 메서드에 addBtnDelsListener() 메서드를 추가합니다. </p><p>복사선 메소드 addBtnCpsListener()</p><p>COPY 버튼을 다시 보면 이벤트 리스너를 추가하는 방법은 위와 동일합니다. </p><p>innerHTML이 읽기 전용이 아닌 경우 tr 요소를 createElement한 다음 newTr.innerHTML=thisTr.innerHTML을 사용할 수 있습니다. </p><p>호환성을 위해 일부 변경이 필요합니다. </p><p>사실 복사는 새로운 행을 만드는 것으로 간주할 수 있습니다. 유일한 차이점은 새 행의 텍스트 입력 상자 내용이 복사된 행과 동일해야 한다는 것입니다. </p><p>쉽죠. 먼저 createTr() 메서드를 호출한 다음 마지막 요소 lastChild의 텍스트 상자 값을 복사된 행과 동일하게 설정할 수 있습니다. </p><p>생각이 있습니다. 코드는 다음과 같습니다. </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">로그인 후 복사</div></div><p>최적화 및 수정</p><p>몇 가지 최적화 및 수정 수행: </p><p>var elements = new Array(); </p><p>수정됨: var elements = [];</p><p>이유: 배열에는 []를 사용하는 것이 더 좋습니다</p><p>vBtnDels[i].onclick 변경 = addBtnDelsListener 메소드의 function() {</p><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">로그인 후 복사</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">로그인 후 복사</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">로그인 후 복사</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>

로그인 후 복사

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

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


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿