ホームページ  >  記事  >  ウェブフロントエンド  >  ピュアネイティブjsでテーブルテーブルの追加・削除を実現

ピュアネイティブjsでテーブルテーブルの追加・削除を実現

高洛峰
高洛峰オリジナル
2017-01-07 10:12:371234ブラウズ

会社のインターンさんからテーブルの追加と削除について質問されましたが、jQueryを使って実装するのはとても簡単でした。また、jQuery を使用せずに js のみを使用して実装する方法についても尋ねました。

このような状況に直面したとき、私の通常のアプローチは「理解できないが、サポートする」です。

私は jQuery をよく使ってきましたが、人々はあまりにも怠け者ですが、この操作を実装するのに依然として js を使用していましたが、問題は IE との互換性にあると思います。 。 。

コードを見つけるだけの場合は、分析プロセスをスキップできます。完全なコードは記事の最後に添付されています。

以下はコーディングプロセスです:

HTML構造コード

いくつかの簡単なスタイルが追加された基本的なテーブル構造、作成、クリア、および1つの予約に対応する3つのボタン。

<!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>

Constructor(擬似コンストラクター)

検討すると、隠し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) を使用する必要があるため、互換性の問題を解決するには、FF、Chrome では

setAttribute(class, value) を使用できます。 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 では互換性の問題があるため、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; 
 } 
}
です

ソート以外にも他の操作が必要なので、reSequence()メソッドを一元管理するinit()メソッドを作成し、createTr()の最後でinit()メソッドを呼び出します。 ) 方法。

ClearTrs()

DOM オブジェクトを削除/破棄するには、remove() メソッドが最初に思い浮かびますが、残念ながら、IE ブラウザの互換性の問題があるため、より簡単な方法が採用されています。 innerHTML="" で、コードは次のとおりです

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

IE8 は「不明な実行エラー」というエラーを報告します。 IE8 の table.innerHTML は読み取り専用属性なので、次のことを確認しました。再度変更します:

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

行の削除メソッド addBtnDelsListener()

次に、現在の行を削除するメソッドを DELETE ボタンにバインドします。

互換性の問題を解決するために、インターネットで提供されている方法は、異なるブラウザー (IE、非 IE) にそれぞれ addEventListener メソッドとattachEvent メソッドを使用することです。

私は別の解決策を使用します:

obj.onclick = function。 (){};

匿名関数のメソッド本体は、上記の clearTrs() メソッドから経験と教訓を学び、deleteRow(index) メソッドを直接使用します。

注意すべき点は、先頭にはあと 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() メソッドを通じて並べ替えます。

また、addBtnDelsListener() メソッドを init() メソッドに追加します。

コピーラインメソッドaddBtnCpsListener()

COPYボタンをもう一度見てみましょう。イベントリスナーを追加する方法は上記と同じです。

innerHTML が読み取り専用でない場合は、createElement と tr 要素を組み合わせて 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 = [];

Reason : 配列は addBtnDelsListener メソッドで [ ]Better

Place vBtnDels[i].onclick = 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 までご連絡ください。