2012/09/01

jQuery 在表格新增一列

學 javascript 沒多久,剛開始只是很簡單的置換文字、為元素加上類別,短短幾行沒什麼感覺。到了開始動態新增表格資料時,javascript 程式碼裡面參雜 HTML 就越看越噁心。
function addRow( data ){
   $('#user-list > tbody ').append(
         '<tr> ' + 
            '<td>' + id + '</td>' +
            '<td>' + username + '</td>' +
            '<td>' + email + '</td>' +
         '</tr>'
      );
}

這樣的寫法除了可讀性很低以外,之後若修改表格結構以及 CSS 樣式時,必須同時修改樣板以及 javascript 內容,不容易維護。

今天翻了翻 jQuery docs,發現幾個方法拿出來用可以把 HTML 和 javascript 切割的頗乾淨。

先定義一列當作表格樣板,可以在 CSS 將這一列隱藏:
<table border="1">
  <tbody>
    <tr id="template" style="display: none;">
      <td class="id some-other-class"> </td>
      <td class="username"> </td>
      <td class="email"> </td>
    </tr>
  </tbody>
</table>

新增一列時,將 template 複製一份出來,再依照 class 名稱將資料填入不同欄位:
function addRow(){
  $('tr:last').after( $('#template').clone().removeAttr('id') );
  $('tr:last > td.id').text( id );
  $('tr:last > td.username').text( username );
  $('tr:last > td.email').text( email );
}


6 則留言:

  1. 這種寫法執行效能會非常不好,因為會讓 jQuery 反覆做了很多 DOM 處理
    少量的增加列沒差,一次增加多一點的時候就....(切身之痛)

    建議可以用 temptle engine 的方式來完成類似這樣的目標,不僅更容易維護(或者說讓 code 更不噁心),效能也會比較好

    javascript 或 jQuery 有很多 template engine,目前我是比較喜歡 jQuery.tmpl

    參考看看 ^^

    回覆刪除
  2. 的確,這個作法欄位和資料一多,動作也會跟著變多。看了 jQuery.tmpl 的文件,他能將 json 格式資料放進樣板中,處理好以後一次輸出。

    但這樣 javascript 裡會有一份表樣板,HTML 或是動態網站後端會有另外一份,當表格結構有異動時,不就要一次改二個地方?

    回覆刪除
  3. 樣板是定義在 HTML 檔案中的,所以如果資料內容不變
    而只是呈現的方式改變的話,那就只需要改樣板即可
    以 PHP 來說,樣板都是定義在 HTML 中
    而 javascript 也定義在 HTML 中
    除非你拆成好幾個樣板來寫,否則都只需要改一個 HTML 樣板檔案即可
    呈現與資料邏輯完全分離,更動時要改的地方也會降到最少

    回覆刪除
  4. 我想我現在比較了解你的意思了

    如果後端程式的樣板會輸出一次表格的內容,然後在前端時又可以前端動態產生新的列
    那麼異動時的確會需要改到兩個地方,一個是後端用樣板,另一個是前端用樣板

    這種情況目前我不知道有什麼現成的解決方案(我想應該已經有了吧,但我沒發現而已)

    不過即使沒有,倒是可以自己實作一下
    改一下現有的後端 temptle engine 或自己寫一個
    原理就是讓後端 template 渲染前,依據定義先複製出另一個一模一樣的樣板供前端使用
    這麼一來,每次更動資料結構,只需要改一個地方,就是後端的樣板

    回覆刪除
  5. 遇到上述的情況,如果單純只用 clone() 表格列,也要改到兩個地方,對吧?
    一個是給後端用的表格列,一個是給前端用的表格列(被隱藏的)

    回覆刪除
  6. 我碰到的情況比較簡單,PHP 依照要求傳回指定的 HTML 樣板,樣板中的 javascript 收到事件時在向伺服器撈資料。

    上面的過程中,PHP 讀取樣板時,保留原本表格的樣板不把資料填入,直到 document.ready() 事件觸發再由 javascript 統一向伺服器取得資料填入。這個方式用 clone() 時是可以只用一個表格樣板的。


    看了您昨天的回覆,我有在想另一個作法。jQuery 有提供 html() 可以讀取片段程式碼,所以可以直接將樣板語法寫在 HTML 裡面,載入資料時以樣板方式處理:
    <tr id="template>
     <td> {$id} </td>
     <td> {$username} </td>
     <td> {$email} </td>
    </tr>

    回覆刪除