2

タイトルはあまり説明的ではありませんが、より良いタイトルが見つかりませんでした。自由に編集してください。

基本的に私が探しているのは、次のことを行うための最良の方法です。

新しいアイテムを追加

ユーザーが [新しい項目を追加] をクリックすると、上記のように同じテキスト ボックスとドロップダウンを含む新しい行が追加されます。私が考えることができるオプションは次のとおりです。

  • JavaScript コードで HTML をハードコーディングします。これは明らかにひどく醜い解決策です。
  • DOM ノード (または jQuery オブジェクト) から HTML を組み立てます。これも非常にまずいです。
  • クライアント側のテンプレート システムを使用します。私はそれらの 1 つを一度使用しましたが、かなり奇妙でした (<script language="html">タグを使用してテンプレートを定義していました)。
  • アドホックなクライアント側の「テンプレート」を作成し、CSS で何とか非表示にします。
  • HTML を取得する AJAX 要求を行います。これは遅く、サーバー リソースを不必要に使用します。

何を指示してるんですか?上記の解決策のいずれにも完全に満足しているわけではありません。

4

4 に答える 4

1

すでに受け入れられている回答があることは承知していますが、同じことを達成するための単純な JavaScript 手段を提供したいと思いました。

function closest(el, tag) {
    if (!el || !tag) {
        return false;
    }
    else {
        var curTag = el.tagName.toLowerCase();
        return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag);
    }
}

function addRow(el) {
    if (!el) {
        return false;
    }
    else {
        var tr = closest(el, 'tr').previousElementSibling,
            newRow = tr.cloneNode(true);
        tr.parentNode.insertBefore(newRow, tr.nextSibling);
    }
}

document.getElementById('add').onclick = function() {
    addRow(this);
}​

JS フィドルのデモ

を実装していないブラウザに対処するための単純な shim を追加するために、上記を少し修正しましたpreviousElementSibling

function closest(el, tag) {
    if (!el || !tag) {
        return false;
    }
    else {
        var curTag = el.tagName.toLowerCase();
        return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag);
    }
}

function prevElementSiblingShim(el) {
    if (!el) {
        return false;
    }
    else {
        var prevSibling = el.previousSibling;
        return prevSibling.nodeType == 1 ? prevSibling : prevElementSiblingShim(prevSibling);
    }
}

function addRow(el) {
    if (!el) {
        return false;
    }
    else {
        var par = closest(el, 'tr'),
            tr = par.previousElementSibling || prevElementSiblingShim(par),
            newRow = tr.cloneNode(true);
        tr.parentNode.insertBefore(newRow, tr.nextSibling);
    }
}

document.getElementById('add').onclick = function() {
    addRow(this);
}​

参考文献:

于 2012-11-13T20:07:43.197 に答える
1

ページで jquery や sencha などのフレームワークを既に使用している場合は、それを利用することもできます。

それ以外の場合は、できるだけシンプルにします。これは非常に重要なコア機能のようには見えないため、追加の https 要求やライブラリ全体の読み込みを必要とするものを作成しないでください。html の複製または生成はエレガントに見えないかもしれませんが、次のようになります。

  • 実装が速い
  • 読みやすいのでデバッグしやすい
  • リソースの浪費が少なく、非常に高速
  • 安定
  • サーバー側のコードや追加の http リクエストは必要ありません
  • 必要に応じて後で実装を簡単に変更できます

これほど些細なことでやり過ぎになるようなものを作成しないでください。

于 2012-11-13T19:48:39.583 に答える
1

非常に単純なアプローチと、フォーマットがテーブルにあると仮定します。

<table>
    <tr>
        <td><input type="text" name="item_name" placeholder="item name" /></td>
        <td><select name="item_type"><option value="" selected="selected">Type</option></select></td>
    </tr>
    <tr>
        <td><input type="text" name="item_name" placeholder="item name" /></td>
        <td><select name="item_type"><option value="" selected="selected">Type</option></select></td>
    </tr>
    <tr>
        <td colspan="2" id="add">+ Add new item</td>
    </tr>
</table>

以下を使用できます。

$('#add').on('click',function(e){
    var $this = $(this);
    var $newRow = $this.closest('table').find('tr:first').clone();
    $newRow.find(':input').val('');
    $newRow.insertBefore($this.parent());
});

内訳:

  1. クリック イベントをバインドしやすくするために、最後のアイテムに ID を与えます。
  2. jQuery を使用して、クリック イベントをその ID にバインドします。
    • $this.closest('table')( )内でクリックしている現在のテーブルを取得します
    • そのテーブル内の最初の行を見つけて複製します ( .clone())
    • 存在する可能性がある入力済みの値を削除します ( .find(':input').val(''))
    • この新しい複製された行を、「新しい項目の追加」行のすぐ上のテーブルに追加します ( $newRow.insertBefore(...))

テンプレート アプローチを使用することもできますが、それは実際にはあなた次第であり、出力をどの程度制御したいかによって異なります。

于 2012-11-13T19:49:15.480 に答える
0

HTML を文字列から DOM に挿入するのが最も効率的な方法です。一度に何百も挿入しない限り、それは問題ではありません。

于 2012-11-13T19:46:41.703 に答える