Frage Best Practice zum Einfügen großer HTML-Teile in Elemente mit Javascript?


Ich baue eine Web-Anwendung (unter Verwendung eines Prototyps), die das Hinzufügen von großen Teilen von HTML in das DOM erfordert. Die meisten davon sind Zeilen, die Elemente mit allen möglichen Attributen enthalten.

Zur Zeit behalte ich eine leere Zeile HTML in einer Variablen und

var blankRow = '<tr><td>'
    +'<a href="{LINK}" onclick="someFunc(\'{STRING}\');">{WORD}</a>'
    +'</td></tr>';

function insertRow(o) {
    newRow = blankRow
        .sub('{LINK}',o.link)
        .sub('{STRING}',o.string)
        .sub('{WORD}',o.word);
    $('tbodyElem').insert( newRow );
}

Nun, das funktioniert alles gut und schön, aber ist es die beste Praxis?

Ich muss den Code in der blankRow aktualisieren, wenn ich Code auf der Seite aktualisiere, so dass die neuen Elemente, die eingefügt werden, gleich sind. Es wird sucky, wenn ich 40 Zeilen HTML in einem blankRow habe und dann muss ich auch fliehen.

Gibt es einen leichteren Weg? Ich dachte an das Urlencoding und entziffere es dann vor dem Einfügen, aber das würde immer noch eine leere Zeile bedeuten und viel Entkommen.

Was wäre gemein wäre eine eof-Funktion a la PHP et al.

$blankRow = <<<EOF
text
text
EOF;

Das würde keine Flucht bedeuten, aber es würde immer noch einen blankRow brauchen.

Was machst du in dieser Situation?

Gelöst

Beendet mit einem DOMBuilder im Prototyp. Keine anderen Bibliotheken wurden benötigt:

$w('a div p span img table thead td th tr tbody tfoot input').each(function(e) {
        window['$' + e] = function() {
            return new Element(e, arguments[0]);
        }
});

newPart = $div({id: 'partition-4'})
    .insert( $p()
        .insert('<b>Stuff</b>')
    )
    .insert( $p({
        id: 'a-p'})
        .insert('<b>More stuff</b>')
    );

$('parentDiv').insert(newPart);

Siehe meine Lösung Hier oder Hier.


17
2018-05-15 11:00


Ursprung


Antworten:


ist es die beste Praxis?

Nein. In der Tat haben HTML-Injection-Probleme zu Bugs geführt, und im schlimmsten Fall, wenn die injizierten Strings möglicherweise von Benutzern eingereichte Inhalte enthalten, XSS-Sicherheitslücken.

Wenn Sie reinen Textinhalt und Attributwerte in eine HTML-Zeichenfolge einfügen, werden Sie Muss HTML-kodieren sie. In PHP müssen Sie anrufen htmlspecialchars() bei Strings, die in HTML gehen, um das zu tun. In JavaScript erhalten Sie keine integrierte HTML-Escaping-Funktion, Sie müssen also Ihre eigenen erstellen, z. durch die Nutzung s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;') auf der Zeichenfolge in den HTML-Code gehen.

onclick = "someFunc (\ '{STRING} \');"

Das ist eine völlig neue Ebene der Flucht. In einem JavaScript-String-Literal innerhalb eines Event-Handler-Attributs müssten Sie die Zeichenfolge JS-encodieren (\-escaping ' und \ plus ein paar Unicode-Zeichen für die Vollständigkeit) und dann HTML-codieren Sie die Ergebnisse. Andernfalls kann die Zeichenfolge aus dem String-Literal-Begrenzer herausbrechen und beliebigen JS-Code einfügen. Vermeiden Sie Inline-Event-Handler-Attribute in allen Fällen, insbesondere aber beim Templating.

Erstellen von Seiteninhalt mit HTML-Zeichenfolgen saugt. Sie sind sehr wahrscheinlich in der Lage, Fehler zu vermeiden und die Sicherheit Ihrer Anwendung zu gefährden. Verwenden Sie stattdessen DOM-ähnliche Methoden, und Sie müssen sich darüber keine Gedanken machen. Sie scheinen jQuery zu verwenden, versuchen Sie es mit den jQuery 1.4-Elementerstellungs-Verknüpfungen:

$('<tr>').append(
    $('<td>').append(
        $('<a>', {
            href: o.link,
            text: o.word,
            onclick: function() {
                someFunc(o.string);
            }
        })
    )
);

oder, halten Sie Ihre leere Zeile tatsächlich in das Dokument als HTML, aber dann verstecken Sie es (display: none) oder trennen Sie sie zum Startzeitpunkt vom Dokument (removeChild oder jQuery detach). Wenn Sie eine neue Zeile wünschen, klonen Sie die leere Zeile und nehmen Sie die erforderlichen Änderungen vor:

var blankRow= $('#blankRow').detach();

    ...

var newRow= blankRow.clone();
var link= newRow.find('td>a');
link.attr('href': o.link);
link.text(o.word);
link.click(function() {
    someFunc(o.string);
});

Wenn Sie Inhalte aus Zeichenfolgenschablonen erstellen müssen, stellen Sie sicher, dass Ihre Vorlagenfunktion HTML - standardmäßig alle Ersetzungen unterdrückt und Ereignisse anfügt, indem Sie Knoten innerhalb des analysierten Inhalts auswählen, der aufgerufen werden soll click(function() { ... }) auf. Oder verwenden Sie die Ereignisdelegierung (z. B. jQuery live()) um Ereignisse zu verarbeiten, ohne beim Hinzufügen neue Knoten binden zu müssen.


19
2018-05-15 12:08



Sie tun es auf eine gute Weise, und das ist ziemlich schnell in Anbetracht anderer Manieren.

Eine alternative, vermutlich saubere Lösung besteht darin, in JavaScript die DOM-Elemente zu erstellen, die Sie verwenden sollen, indem Sie mehrere aufrufen

document.createElement (TagName);

Aber dein Code wird in meinem Denken umsonst wachsen.

Eine weitere Möglichkeit, DOM zu erstellen, ist, den Code, den Sie kopieren möchten, in den HTML-Body einzufügen, ihm einen className und / oder eine ID wie "template" zu geben, die ihn zusätzlich (mit css) ausblenden und dann Verarbeiten Sie es nach Bedarf, indem Sie das Element zurückholen, es klonen und die gewünschte Eigenschaft festlegen, bevor Sie es anfügen, wo es hingehört


5
2018-05-15 11:20



Wenn ich Sie gut verstehe, geht es bei Ihrer Frage darum, große Strings so zu initialisieren, wie Sie es in PHP (oder Perl) tun werden. Für lange (mehrzeilige) Zeichenfolge verwende ich:

var blankRow = [
     'a line',
     'another line',
     'still more lines',
     'lines lines lines',
     '... etc'
    ].join('')

Sie können auch einen Backslash für die Fortsetzung verwenden, aber das kann etwas unordentlich werden:

var blankRow = 'a line\
another line\
still more lines\
lines lines lines\
... etc';

BEARBEITEN basierend auf Kommentar: Ich bin auch faul! Also benutze ich dies um zu entkommen:

function qs(str){
    str = str || this || '';
    return "'"+str+"'";
}

function qd(str){
    str = str || this || '';
    return '"'+str+'"';

}

String.prototype.qs = qs;
String.prototype.qd = qd;

// applied:
var blankRow = [
         'a line',
         'another '+qd('line'),
         'still more lines',
         'lines '+'lines'.qs()+ ' lines',
         '... etc'
        ].join('');

Problem mit dem Faulenzen: Es ist ziemlich harte Arbeit, seine Faulheit zu bewahren


1
2018-05-15 11:21