This is a table for operations by javascript | ||
---|---|---|
회사 인턴이 테이블 추가 및 삭제에 대해 문의했는데 jQuery를 이용해서 구현하는 방법이 아주 간단했습니다. 그는 또한 jQuery를 사용하지 않고 js만 사용하여 구현하는 방법을 물었습니다.
이러한 상황에 직면했을 때 제가 평소 접근하는 방식은 '이해하지 말고 지지'입니다.
JQuery를 많이 사용하고 사람들이 너무 게으른데, 이 작업을 수행하기 위해 여전히 js를 사용하는 것은 IE 호환성에 있는 것 같습니다. . .
코드만 찾고 싶으신 분은 분석 과정을 건너뛰셔도 됩니다. 전체 코드는 글 하단에 첨부되어 있습니다.
코딩 과정은 다음과 같습니다.
HTML 구조 코드
몇 가지 간단한 스타일이 추가되고 생성, 삭제 및 예약에 해당하는 세 개의 버튼이 있는 기본 테이블 구조입니다. .
<!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>
생성자(의사 생성자)
고려하여 숨겨진 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('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 객체의 생성자는 유사하며 코드는 다음과 같습니다
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()
생성자가 완료된 후 createTr()을 개선합니다. 방법.
예상되는 tr 구조는 일련번호, 텍스트 상자, 작업 버튼입니다.
관련 개체를 순차적으로 생성합니다. 일련번호 열은 동적으로 새로 고쳐야 하므로 먼저 클래스 이름을 설정하고 메소드를 통해 정렬 작업을 수행합니다.
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()
동적 정렬 방법 reSequence()를 만듭니다. Firefox에서는 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() 메소드를 지원하지 않습니다. 온라인에서 해결책을 찾았습니다
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(){}
과 같은 이 메서드를 추가합니다. 안타깝게도 구현되지 않았습니다.
수정된 코드는
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; } }
정렬 외에 다른 작업이 필요하므로 createTr()에 reSequence() 메소드를 중앙에서 관리하기 위한 init() 메소드를 생성합니다. init() 메서드는 메서드 끝에서 호출됩니다.
빈 줄 지우기 메소드clearTrs()
DOM 객체를 제거/파괴하려면 가장 먼저 떠오르는 것은 Remove() 메소드입니다. 안타깝게도 IE 브라우저 호환성 문제가 있습니다. 이므로 더 간단한 방법은 dom 개체에서 innerHTML=""을 실행하는 것입니다. 코드는 다음과 같습니다.
function clearTrs() { vTbody.innerHTML = ''; }
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('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(); }; } }
삭제 작업을 수행한 후 reSequence() 메서드를 통해 재정렬합니다. .
동시에 init() 메서드에 addBtnDelsListener() 메서드를 추가합니다.
복사선 메소드 addBtnCpsListener()
COPY 버튼을 다시 보면 이벤트 리스너를 추가하는 방법은 위와 동일합니다.
innerHTML이 읽기 전용이 아닌 경우 tr 요소를 createElement한 다음 newTr.innerHTML=thisTr.innerHTML을 사용할 수 있습니다.
호환성을 위해 일부 변경이 필요합니다.
사실 복사는 새로운 행을 만드는 것으로 간주할 수 있습니다. 유일한 차이점은 새 행의 텍스트 입력 상자 내용이 복사된 행과 동일해야 한다는 것입니다.
쉽죠. 먼저 createTr() 메서드를 호출한 다음 마지막 요소 lastChild의 텍스트 상자 값을 복사된 행과 동일하게 설정할 수 있습니다.
생각이 있습니다. 코드는 다음과 같습니다.
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; } } }
최적화 및 수정
몇 가지 최적화 및 수정 수행:
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('thead')[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('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; }
将copyTr()方法中的?:格式修改为if else函数。
修改为:
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; } }
原因:?:预期返回值应该是一个变量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中文网!