Der klarste Weg, um HTML-Elemente in jQuery zu erstellen

73

Ich habe viele verschiedene Stile (und einige verschiedene Methoden) zum Erstellen von Elementen in jQuery gesehen. Ich war neugierig auf den klarsten Weg, sie zu bauen, und auch darauf, ob eine bestimmte Methode aus irgendeinem Grund objektiv besser ist als eine andere. Im Folgenden finden Sie einige Beispiele für die Stile und Methoden, die ich gesehen habe.

var title = "Title";
var content = "Lorem ipsum";

// escaping endlines for a multi-line string
// (aligning the slashes is marginally prettier but can add a lot of whitespace)
var $element1 = $("\
    <div><h1>" + title + "</h1>\
        <div class='content'>  \
        " + content + "        \
        </div>                 \
    </div>                     \
");

// all in one
// obviously deficient
var $element2 = $("<div><h1>" + title + "</h1><div class='content'>" + content + "</div></div>");

// broken on concatenation
var $element3 = $("<div><h1>" +
                title + 
                "</h1><div class='content'>" +
                content +
                "</div></div>");

// constructed piecewise
// (I've seen this with nested function calls instead of temp variables)
var $element4 = $("<div></div>");
var $title = $("<h1></h1>").html(title);
var $content = $("<div class='content'></div>").html(content);
$element4.append($title, $content);

$("body").append($element1, $element2, $element3, $element4);

Bitte zögern Sie nicht, andere Methoden / Stile zu demonstrieren, die Sie möglicherweise verwenden.

bkconrad
quelle
1
Warum verwenden Sie in den drei ersten Beispielen jquery? Das Schreiben eines vollständigen HTML-Codes in einen JQuery-Selektor ist nur ein Leistungsverlust. var element2 = "<div><h1>"+title+"</h1>...</div>";
Julien Lafont
Ich manipuliere diese Elemente auch mit jQuery. Wenn ich sie also nicht mit jQuery erstellen würde, müsste ich sowieso einen jQuery-Selektor verwenden.
Bkconrad

Antworten:

73

Vorlagen sind großartig und wenn Sie in Ihrem Projekt Zugriff darauf haben, empfehle ich Ihnen, sie zu verwenden. Wenn Sie Underscore oder Lodash verwenden, ist es integriert. In einigen Fällen müssen Sie jedoch HTML in Ihren Code einbauen , unabhängig davon, ob es sich um Refactoring oder Testen handelt. Ich habe festgestellt, dass das folgende Format am klarsten zu lesen ist, wenn dies erforderlich ist.

Hinweis: Die HTML-Spezifikation erlaubt einfache ODER doppelte Anführungszeichen für Attribute in Ihrem Markup.

this.$fixture = $([
  "<div>",
  "  <div class='js-alert-box'></div>",
  "  <form id='my-form-to-validate'>",
  "    <input id='login-username' name='login-username'>",
  "  </form>",
  "</div>"
].join("\n"));
Baer
quelle
9
Beeindruckend! Absolut perfekt. Es dauerte fast zwei Jahre, um eine Antwort auf die eigentliche Frage zu erhalten, die lesbar und leicht zu pflegen ist.
Bkconrad
3
Ich mag das. Was würden Sie .join("\n")stattdessen denken .join("")?
Jeffery Thomas
2
Beachten Sie, dass Sie in Typoskript Vorlagenzeichenfolgen basarat.gitbooks.io/typescript/docs/template-strings.html verwenden können
Ronnie
47

Nachdem ich mich eine Weile umgesehen hatte, fand ich den Stil, für den ich mich schließlich entschieden hatte. Zuerst werde ich sagen, dass ich Moustache als Vorlage verwendet habe, und es hat gut funktioniert. Manchmal müssen Sie ein Element jedoch nur einmal erstellen, ohne es wiederzuverwenden, oder eine andere Motivation haben, keine andere Bibliothek einzubringen. In dieser Situation habe ich Folgendes verwendet:

$("body")
.append(
    $("<div>")
    .append(
        $("<div>")
        .append(
            $("<h1>").text(title)
        )
    )
    .append(
        $("<div>").text(content)
    )
);​

Dies funktioniert , weil append()eine Referenz auf das Objekt , das Sie angehängt an , so gekettet append()befestigen s auf das gleiche Objekt. Bei korrekter Einrückung ist die Struktur des Markups offensichtlich und auf diese Weise leicht zu ändern. Dies ist natürlich langsamer als die Verwendung von Vorlagen (das Ganze muss Stück für Stück erstellt werden), aber wenn Sie es nur für die Initialisierung oder ähnliches verwenden, ist dies ein großartiger Kompromiss.

Es gibt viele Möglichkeiten, ein Konstrukt wie dieses zu formatieren, aber ich habe einen Weg gewählt, um klar zu machen, was los ist. Die Regel, die ich verwendet habe, ist, dass in jeder Zeile maximal eine öffnende Klammer und / oder eine schließende Klammer stehen sollte. Außerdem müssen die Blätter dieser Anhängebäume nicht an den jQuery-Konstruktor übergeben werden, aber ich habe dies hier zur visuellen Wiederholung getan.

bkconrad
quelle
4
Bei weitem die sauberste jQuery-ähnliche Methode, als sie in Anführungszeichen zu setzen, wie in der akzeptierten Antwort gezeigt. Die akzeptierte Antwort fühlt sich an wie HTML-Code in einem PHP echo/
Shudder
6
$("<h1>" + title + "</h1>")könnte sein$("<h1>").text(title)
Bob Stein
4
.append()Beeinträchtigen all diese Aufrufe die Leistung im Vergleich zum Erstellen einer Zeichenfolge (z. B. in einer Variable) und zum Anhängen einer Zeichenfolge .append()?
Scribblemacher
Es kann nützlich sein, sich daran zu erinnern, dass .append()auch ein Array akzeptiert werden kann. Dies kann nützlich sein, wenn Sie beispielsweise versuchen, Listen zu erstellen. Kann dann eine anonyme Funktion verwenden, die selbst aufruft, um die Liste von zu generieren <li>s. [So etwas wie .append( (function () { ... return li; })() )]
Fabien Snauwaert
@adamj - Ich bin das Gegenteil - Ich bevorzuge die akzeptierte Version, da sie leichter zu lesen ist, da sie tatsächlich einem verschachtelten Markup ähnelt.
Martin James
32

Beim Erstellen von DOMs versuche ich, Zeichenfolgenverkettungen zu vermeiden, da diese zu subtilen Fehlern und nicht ordnungsgemäß codierten Ausgaben führen können.

Ich mag dieses:

$('<div/>', {
    html: $('<h1/>', {
        html: title
    }).after(
        $('<div/>', {
            'text': content,
            'class': 'content'
        })
    )
}).appendTo('body');

erzeugt:

    ...
    <div><h1>some title</h1><div class="content">some content</div></div>
</body>

und es stellt eine korrekte HTML-Codierung und DOM-Baumerstellung mit übereinstimmenden öffnenden und schließenden Tags sicher.

Darin Dimitrov
quelle
1
Ich wollte ein Beispiel dafür hinzufügen, aber ich hatte es nie lesbar gesehen. Diese Methode ist jedoch ziemlich klar.
Bkconrad
23

Mein Rat: Versuchen Sie nicht, HTML-Elemente mit jQuery zu erstellen, es liegt nicht in der Verantwortung.

Verwenden Sie ein Javascript-Template-System wie Moustache oder HandlebarJs .

Mit einer sehr begrenzten Anzahl von Zeilen können Sie Ihre HTML-Elemente direkt aus einem Javascript-Objekt erstellen. Es ist nicht kompliziert, nur 2 Funktionen und eine Vorlage.

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>

var context  = {title: "My New Post", body: "This is my first post!"}
var template = Handlebars.compile($("#template-skeleton"));
var html     = template(context);

Edit:
Ein weiteres Beispiel ohne HTML, reines Javascript (von ICanHaz ):

var skeleton = '<div><h1>{{title}}</h1><div class="content">{{content}}</div></div>';
var data = { title: "Some title", content: "Some content" };
var html = Mustache.to_html(skeleton, data);

Es ist viel wartbarer als eine Reihe von Verkettungen.

Julien Lafont
quelle
Ich hatte mich nicht viel mit Template-Systemen beschäftigt. Ich mag diese Syntax sehr. Derzeit arbeite ich jedoch in einem MVC-Framework, und mein Javascript ist gut von meinen tatsächlichen Ansichtsvorlagen getrennt. Dies bedeutet, dass meine js-Vorlagen ohnehin als Zeichenfolgen (in ihren jeweiligen .js-Dateien) erstellt werden müssen, oder dass das Gesetz des Demeters verletzt wird, indem nach einer in der HTML-Vorlage definierten js-Vorlage gegriffen wird. +1 unabhängig davon, da dies in jeder anderen Situation eine gute Lösung wäre.
Bkconrad
Es scheint nicht unvereinbar. Siehe mein zweites Beispiel.
Julien Lafont
Nachdem ich es tatsächlich ausprobiert hatte, stellte sich heraus, dass dies eine wirklich gute Lösung war. Die Syntax ist offensichtlich und da diese Vorlagen so klein sind, sehen sie gut aus, wenn sie direkt in die .js-Dateien eingebettet sind. Außerdem kann ich die Zeilenumbrüche weiterhin verwenden, wenn meine Vorlagen verrückt werden.
Bkconrad
13

Antwort 2015 : Verwenden Sie für ältere Browser mehrzeilig .

var str = multiline(function(){/*
<!doctype html>
<html>
    <body>
        <h1>❤ unicorns</h1>
    </body>
</html>
*/});

Verwenden Sie für ES6 JavaScript-Vorlagenzeichenfolgen

var str = `
<!doctype html>
<html>
    <body>
        <h1>❤ unicorns</h1>
    </body>
</html>`
Mikemaccana
quelle
Dies ist so viel einfacher als die Verwendung von .appends überall.
Chris Akridge
7

Dies ist aus Bärs Antwort übernommen. Ich finde es besser lesbar, keine Notwendigkeit, ein Array zu erstellen und zu verbinden, keine Notwendigkeit, jede Zeile in Anführungszeichen zu setzen:

http://jsfiddle.net/emza5Ljb/

var html =

    '                                                           \
      <div>                                                     \
        <div class="js-alert-box"></div>                        \
        <form id="my-form-to-validate">                         \
          <input id="login-username" name="login-username">     \
        </form>                                                 \
      </div>                                                    \
    '

// using jQuery:
//
var dom = $( html )

// or if you need performance, don't use jQuery
// for the parsing.
// http://jsperf.com/create-dom-innerhtml-vs-jquery
//
var div       = document.createElement( 'div' )
div.innerHTML = html
var dom = $( div )

Zu Ihrer Information, wenn die Leistung kein Problem darstellt und Elemente viele dynamische Daten enthalten, schreibe ich manchmal einfach Code wie diesen (beachten Sie, dass der Closure-Compiler eine Warnung über die nicht zitierte Klasseneigenschaft ausgibt, aber in modernen Browsern funktioniert dies einwandfrei):

$(
      '<a></a>'

    , {
           text     : this.fileName
         , href     : this.fileUrl
         , target   : '_blank'
         , class    : 'file-link'
         , appendTo : this.container
      }
)

quelle
2

Hier ist ein Beispiel, das $ (htmlString) verwendet und das Standardlayout von HTML-Code nachahmt:

function getPage(title, contents) {
  return (
    $("<div>", {id: "container", class: "box"}).append(
      $("<div>", {class: "title"}).append(
        $("<h1>").text(title)
      ),
      $("<div>").html(contents)
    )
  );
}
tokland
quelle
2

Ich finde den funktionalen Ansatz sehr praktisch. Zum Beispiel

// reusable generics TABLE constructor helpers
var TD = function(content) { return $('<td>', { html: content }) }
var TH = function(content) { return $('<th>', { html: content }) }
var TR = function(cell, cells) {  // note the kind of cell is a 2^order parameter
    return $('<tr>', { html: $.map(cells, cell) })
}

// application example
THEAD = $('<thead>', {html:
    TR(TH, [1,2,3,4])})
TBODY = $('<tbody>', {html: [
    TR(TD, ['a','b','c','d']),
    TR(TD, ['a','b','c','d']),
]})

jetzt der anruf

$('#table').append($('<table>', {html: [THEAD, TBODY]}))

ergibt

<table><thead><tr><th>1</th><th>2</th><th>3</th><th>4</th></tr></thead><tbody><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr></tbody></table>

bearbeiten

Ich habe meinen Ansatz verfeinert, der jetzt beispielsweise als html_uty.js verfügbar ist

CapelliC
quelle
1
Sie verwenden, htmlals wäre es ein Attribut, wie in { html: content }, aber es scheint sich anders zu verhalten. Wo ist dieses interessante Feature dokumentiert ?
Bob Stein
1
Vielleicht nach As of jQuery 1.8, any jQuery instance method (a method of jQuery.fn) can be used as a property...Aber ich erinnere mich vage, dass ich es durch Ausprobieren gefunden habe, nicht durch Dokumente, während ich versucht habe, meine Mini-Skripte zu erstellen, die wie Reaktionen reagieren. Übrigens habe ich jetzt das Konstrukt verfeinert (speziell der Stil attr kann nicht direkt behandelt werden, ich werde einen Link zu github in die Antwort
einfügen
1
Ich mag dieses Scripting ohne Vorlagensprache sehr. Es beugt immer noch mein Gehirn (wie es $ .map immer tut, ganz zu schweigen davon, dass Sie ein Array an $ .html übergeben), aber ich werde weiter suchen.
Bob Stein
0

Einfachste Art dies zu tun -

var optionsForLength = 
'<option value="Kilometre">Kilometre</option>'+
'<option value="Metre">Metre</option>'+
'<option value="Centimetre">Centimetre</option>'+
'<option value="Milimetre">Milimetre</option>'+
'<option value="Micrometre">Micrometre</option>'+
'<option value="Nanometre">Nanometre</option>'+
'<option value="Mile">Mile</option>'+
'<option value="Yard">Yard</option>'+
'<option value="Foot">Foot</option>'+
'<option value="Inch">Inch</option>'+
'<option value="Nautical mile">Nautical mile</option>';
Muhammad Tarique
quelle