>웹 프론트엔드 >JS 튜토리얼 >순수 네이티브 js는 테이블 추가 및 삭제를 실현합니다.

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

高洛峰
高洛峰원래의
2017-01-07 10:12:371322검색

회사 인턴이 테이블 추가 및 삭제에 대해 문의했는데 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 작업을 수행하려면 코드 하단의 36cc49f0c466276486e50c850b7e4956 앞에 3f1c4e4b6b16bbbd69b2ee476dc4f83a를 배치하세요.

테이블의 tbody를 기반으로 추가 및 삭제 작업을 수행하려면 먼저 이 전역 변수를 선언하면 됩니다.

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

객체를 생성하려면 document.createElement 메서드를 사용할 수 있습니다.

객체 지향 방식으로 프로그래밍하면 가장 안쪽 요소부터 시작하여 생성자를 먼저 작성합니다(실제로는 표준 생성자 형식이 아닙니다).

td에는 텍스트, 버튼과 같은 양식 요소가 있을 수 있으므로 먼저 입력 생성자 함수 myInput(vId, vClass, vType, vValue, vParent)를 만듭니다.{}

다음은 하나입니다. 호환성 문제는 IE 커널이 setAttribute(class, value)를 지원하지 않으며 setAttribute(className, value)를 사용해야 한다는 것입니다. 따라서 호환성 문제를 해결하려면

setAttribute(class, FF 및 Chrome의 경우 .

IE의 경우 setAttribute(className, value)

여기에 .className의 또 다른 방법이 있습니다. 코드는 다음과 같습니다.

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); 
 } 
}

그런 다음 td 객체와 tr 객체의 생성자는 유사하며 코드는 다음과 같습니다

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; 
}

새 행 메서드 createTr()

생성자가 완료된 후 createTr()을 개선합니다. 방법.

예상되는 tr 구조는 일련번호, 텍스트 상자, 작업 버튼입니다.

관련 개체를 순차적으로 생성합니다. 일련번호 열은 동적으로 새로 고쳐야 하므로 먼저 클래스 이름을 설정하고 메소드를 통해 정렬 작업을 수행합니다.

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); 
}

정렬 방법 reSequence()

동적 정렬 방법 reSequence()를 만듭니다. Firefox에서는 innerText가 효과가 없으므로 innerHTML이 사용됩니다. 코드는 다음과 같습니다.

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

IE8 이하에서는 getElementsByClassName() 메소드를 지원하지 않습니다. 온라인에서 해결책을 찾았습니다

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; 
 }; 
}

Object 또는 HTMLTableSectionElement의 프로토타입에

HTMLTableSectionElement.prototype.getElementsByClassName = function(){}

과 같은 이 메서드를 추가합니다. 안타깝게도 구현되지 않았습니다.

수정된 코드는

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; 
 } 
}

정렬 외에 다른 작업이 필요하므로 createTr()에 reSequence() 메소드를 중앙에서 관리하기 위한 init() 메소드를 생성합니다. init() 메서드는 메서드 끝에서 호출됩니다.

빈 줄 지우기 메소드clearTrs()

DOM 객체를 제거/파괴하려면 가장 먼저 떠오르는 것은 Remove() 메소드입니다. 안타깝게도 IE 브라우저 호환성 문제가 있습니다. 이므로 더 간단한 방법은 dom 개체에서 innerHTML=""을 실행하는 것입니다. 코드는 다음과 같습니다.

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

IE8에서는 '알 수 없는 실행 오류'라는 오류를 보고합니다. IE8의 table.innerHTML은 읽기 전용 속성이기 때문에 다음을 확인했습니다. 젠장! 다시 변경:

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

행 삭제 메소드 addBtnDelsListener()

다음으로 현재 행을 삭제하는 메소드를 DELETE 버튼에 바인딩합니다.

호환성 문제를 해결하기 위해 인터넷에서 제시하는 방법은 브라우저별로(IE, non-IE) addEventListener, attachmentEvent 메소드를 각각 사용하는 것입니다.

다른 솔루션을 사용합니다. :

obj.onclick = function(){};

익명 함수의 메서드 본문은 위의clearTrs() 메서드에서 경험과 교훈을 얻었으며 deleteRow(index)를 직접 사용합니다. ) 방법.

한 가지 주의할 점은 thead에 행이 2개 더 있기 때문에 thisTr.rowIndex에서 얻은 행 수가 현재 행보다 2개 더 많다는 것입니다. 따라서 현재 인덱스 수 = thisTr.rowIndex-vThead.rows.length

코드는 다음과 같습니다.

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(); 
  }; 
 } 
}

삭제 작업을 수행한 후 reSequence() 메서드를 통해 재정렬합니다. .

동시에 init() 메서드에 addBtnDelsListener() 메서드를 추가합니다.

복사선 메소드 addBtnCpsListener()

COPY 버튼을 다시 보면 이벤트 리스너를 추가하는 방법은 위와 동일합니다.

innerHTML이 읽기 전용이 아닌 경우 tr 요소를 createElement한 다음 newTr.innerHTML=thisTr.innerHTML을 사용할 수 있습니다.

호환성을 위해 일부 변경이 필요합니다.

사실 복사는 새로운 행을 만드는 것으로 간주할 수 있습니다. 유일한 차이점은 새 행의 텍스트 입력 상자 내용이 복사된 행과 동일해야 한다는 것입니다.

쉽죠. 먼저 createTr() 메서드를 호출한 다음 마지막 요소 lastChild의 텍스트 상자 값을 복사된 행과 동일하게 설정할 수 있습니다.

생각이 있습니다. 코드는 다음과 같습니다.

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; 
  } 
 } 
}

최적화 및 수정

몇 가지 최적화 및 수정 수행:

var elements = new Array();

수정됨: var elements = [];

이유: 배열에는 []를 사용하는 것이 더 좋습니다

vBtnDels[i].onclick 변경 = addBtnDelsListener 메소드의 function() {

修改为: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中文网!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.