jQuery document.createElement ekwiwalent?

1251

Refaktoryzuję stary kod JavaScript i dzieje się wiele manipulacji DOM.

var d = document;
var odv = d.createElement("div");
odv.style.display = "none";
this.OuterDiv = odv;

var t = d.createElement("table");
t.cellSpacing = 0;
t.className = "text";
odv.appendChild(t);

Chciałbym wiedzieć, czy istnieje lepszy sposób na wykonanie tego za pomocą jQuery. Eksperymentowałem z:

var odv = $.create("div");
$.append(odv);
// And many more

Ale nie jestem pewien, czy to jest lepsze.

Rob Stevenson-Leggett
źródło
jsben.ch/#/ARUtz - test porównawczy dla jquery vs createElement
EscapeNetscape
Możliwy duplikat tworzenia elementu div w jQuery
T.Todua
Błąd typu Uncaught: $ .create nie jest funkcją
Tyguy7

Odpowiedzi:

1290

Oto twój przykład w linii „jeden”.

this.$OuterDiv = $('<div></div>')
    .hide()
    .append($('<table></table>')
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

Aktualizacja : Myślałem, że zaktualizuję ten post, ponieważ nadal generuje duży ruch. W komentarzach poniżej jest trochę dyskusji na temat $("<div>")vs $("<div></div>")vs $(document.createElement('div'))jako sposobu tworzenia nowych elementów i który jest „najlepszy”.

Złożyłem mały test porównawczy , a oto z grubsza wyniki powtarzania powyższych opcji 100 000 razy:

jQuery 1.4, 1.5, 1.6

               Chrome 11  Firefox 4   IE9
<div>            440ms      640ms    460ms
<div></div>      420ms      650ms    480ms
createElement    100ms      180ms    300ms

jQuery 1.3

                Chrome 11
<div>             770ms
<div></div>      3800ms
createElement     100ms

jQuery 1.2

                Chrome 11
<div>            3500ms
<div></div>      3500ms
createElement     100ms

Myślę, że nie jest to duża niespodzianka, ale document.createElementjest najszybszą metodą. Oczywiście, zanim odejdziesz i zaczniesz refaktoryzować całą bazę kodu, pamiętaj, że różnice, o których tutaj mówimy (we wszystkich, oprócz archaicznych wersji jQuery), wynoszą około 3 dodatkowe milisekundy na tysiąc elementów .


Aktualizacja 2

Zaktualizowano dla jQuery 1.7.2 i umieściłem test porównawczy, JSBen.chktóry jest prawdopodobnie bardziej naukowy niż moje prymitywne testy porównawcze, a ponadto można go teraz gromadzić w crowdsourcingu!

http://jsben.ch/#/ARUtz

pseudonim
źródło
70
Przekonasz się, że document.createElement jest znacznie szybszy niż jQuery przekonwertować ciąg HTML na element. (na wypadek, gdybyś chciał zwiększyć efektywność)
Sugendran,
25
Tak jest w przypadku jQuery <1.3 Jest to ekwiwalent prędkości, teraz uważam.
Rob Stevenson-Leggett
15
@Kevin, to prawda, jednak sprawia, że ​​jQuery wykonuje więcej pracy (uruchamia go przez wyrażenie regularne, aby dodać tag zamykający), więc wolę powyższą metodę. Ponadto odróżnia twój kod, $('div')który jest wizualnie bardzo podobny, ale funkcjonalnie różni się między sobą .
nickf
14
Więc w zasadzie kombinacja @Sungendran i @nickf byłaby $(document.createElement('div'))i powinna być najszybsza?
Kolky,
14
Myślę, że „poprawnym” sposobem jest $ („<div />”), przy czym IMO ma jeszcze więcej „znaczenia”, ponieważ jest całkiem oczywiste, że tworzysz Węzeł. Złe jest to, że w ten sposób łamie podświetlanie składni we wszystkich edytorach = (
Erik Escobedo,
139

Po prostu dostarczając HTML elementów, które chcesz dodać do konstruktora jQuery $(), zwróci obiekt jQuery z nowo zbudowanego HTML, odpowiedni do dołączenia do DOM przy użyciu append()metody jQuery .

Na przykład:

var t = $("<table cellspacing='0' class='text'></table>");
$.append(t);

Możesz następnie wypełnić tę tabelę programowo, jeśli chcesz.

Daje to możliwość określenia dowolnego dowolnego kodu HTML, w tym nazw klas lub innych atrybutów, które mogą być bardziej zwięzłe niż używanie, createElementa następnie ustawianie atrybutów takich jak cellSpacingi classNameza pomocą JS.

Adam Bellaire
źródło
7
Być może było to oczywiste i wskazane w twoim przykładzie, ale tworzenie elementu DOM jQuery przy użyciu składni $ („<ciąg html>”) nie może być dołączone do DOM przy użyciu natywnej metody <element> .appendChild lub podobnej. Musisz użyć metody app jQuery.
Adam
4
$(htmlStr)jest implementowany jako document.createElement("div").innerHTML = htmlStr. Innymi słowy, wywołuje parser HTML przeglądarki. Zniekształcony HTML łamie się inaczej w IE niż w innych przeglądarkach.
Matthew
2
@Adam Obiekt jQuery ma getfunkcję, która zwraca natywny element DOM. (Wiem, że ten temat jest stary, ale dodam go w celach informacyjnych ;-))
Constantino Tsarouhas
1
Jeśli masz problemy z podejściem html strun do analizowania go jQuery.parseHTML
fguillen
1
@Adam Lub, jeśli jest to łatwiejsze w przepływie kodu / oczach, możesz to zrobić[dom element].appendChild($('<html>')[0]);
ACK_stoverflow 18.10.2013
49

Robię tak:

$('<div/>',{
    text: 'Div text',
    class: 'className'
}).appendTo('#parentDiv');
kami
źródło
44

ponieważ jQuery1.8użycie $.parseHTML()do tworzenia elementów jest lepszym wyborem.

istnieją dwie korzyści:

1. jeśli używasz starego sposobu, który może być podobny $(string), jQuery zbada ciąg znaków, aby upewnić się, że chcesz wybrać znacznik HTML lub utworzyć nowy element. Używając tego $.parseHTML(), mówisz jQuery, że chcesz utworzyć nowy element, więc wydajność może być nieco lepsza.

2. znacznie ważniejsze jest to, że możesz cierpieć z powodu ataku krzyżowego ( więcej informacji ), jeśli używasz starego sposobu. jeśli masz coś takiego:

    var userInput = window.prompt("please enter selector");
    $(userInput).hide();

zły facet może się <script src="xss-attach.js"></script>do ciebie drażnić. na szczęście $.parseHTML()uniknij tego zawstydzenia:

var a = $('<div>')
// a is [<div>​</div>​]
var b = $.parseHTML('<div>')
// b is [<div>​</div>​]
$('<script src="xss-attach.js"></script>')
// jQuery returns [<script src=​"xss-attach.js">​</script>​]
$.parseHTML('<script src="xss-attach.js"></script>')
// jQuery returns []

Należy jednak zauważyć, że ajest to obiekt jQuery, podczas gdy belement html:

a.html('123')
// [<div>​123​</div>​]
b.html('123')
// TypeError: Object [object HTMLDivElement] has no method 'html'
$(b).html('123')
// [<div>​123​</div>​]
Brian
źródło
„Lepszy wybór” do „stworzenia [dowolnego] elementu” może być mocny. Odpowiedź @ siergiej ma dobrą opinię, mówiąc, że parseHTMLjest dobra dla html pochodzących ze źródeł zewnętrznych, ale że „ wszystkie ulepszenia zniknęły po zawinięciu wyników w nowy obiekt jQuery ”. Oznacza to, że jeśli chcesz na stałe utworzyć nowy element HTML zawinięty w jQuery, $("<div>stuff</div>")styl nadal wygrywa.
ruffin
38

AKTUALIZACJA

Od najnowszych wersji jQuery następująca metoda nie przypisuje właściwości przekazywanych w drugim obiekcie

Poprzednia odpowiedź

Wydaje mi się, że używanie document.createElement('div')razem z jQueryjest szybsze:

$(document.createElement('div'), {
    text: 'Div text',
    'class': 'className'
}).appendTo('#parentDiv');
Om Shankar
źródło
29

Chociaż jest to bardzo stare pytanie, pomyślałem, że byłoby miło zaktualizować je o najnowsze informacje;

Od jQuery 1.8 dostępna jest funkcja jQuery.parseHTML (), która jest obecnie preferowanym sposobem tworzenia elementów. Ponadto istnieją pewne problemy z analizowaniem kodu HTML za pośrednictwem $('(html code goes here)'), na przykład na oficjalnej stronie jQuery w następujących uwagach do wydania :

Zrelaksowana parsowanie HTML: Możesz ponownie mieć spacje lub znaki nowej linii przed tagami w $ (htmlString). Nadal zdecydowanie zalecamy używanie $ .parseHTML () podczas analizowania HTML uzyskanego ze źródeł zewnętrznych i może w przyszłości wprowadzać dalsze zmiany w analizie HTML.

Aby odnieść się do rzeczywistego pytania, podany przykład można przetłumaczyć na:

this.$OuterDiv = $($.parseHTML('<div></div>'))
    .hide()
    .append($($.parseHTML('<table></table>'))
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

co jest niestety mniej wygodne niż używanie samego $(), ale daje większą kontrolę, na przykład możesz wykluczyć tagi skryptu (pozostawi skrypty wbudowane, jak onclickchociaż):

> $.parseHTML('<div onclick="a"></div><script></script>')
[<div onclick=​"a">​</div>​]

> $.parseHTML('<div onclick="a"></div><script></script>', document, true)
[<div onclick=​"a">​</div>​, <script>​</script>​]

Oto punkt odniesienia od najwyższej odpowiedzi dostosowanej do nowej rzeczywistości:

JSbin Link

jQuery 1.9.1

  $ .parseHTML: 88ms
  $ ($. parseHTML): 240ms
  <div> </div>: 138ms
  <div>: 143ms
  createElement: 64ms

Wygląda na to, że parseHTMLjest znacznie bliżej createElementniż $(), ale wszystkie wzmocnienia zniknęły po zawinięciu wyników w nowym obiekcie jQuery

siergiej
źródło
11
var mydiv = $('<div />') // also works
Shimon Doodkin
źródło
6
var div = $('<div/>');
div.append('Hello World!');

Jest najkrótszym / najłatwiejszym sposobem utworzenia elementu DIV w jQuery.

AcidicChip
źródło
5

Właśnie stworzyłem do tego małą wtyczkę jQuery: https://github.com/ern0/jquery.create

Podąża za twoją składnią:

var myDiv = $.create("div");

Identyfikator węzła DOM można określić jako drugi parametr:

var secondItem = $.create("div","item2");

Czy to poważne? Nie. Ale ta składnia jest lepsza niż $ („<div> </div>”) i jest to bardzo dobry stosunek jakości do ceny.

Jestem nowym użytkownikiem jQuery, przełączam się z DOMAssistant, który ma podobną funkcję: http://www.domassistant.com/documentation/DOMAssistantContent-module.php

Moja wtyczka jest prostsza, myślę, że attrs i zawartość lepiej dodawać za pomocą metod łączenia:

$("#container").append( $.create("div").addClass("box").html("Hello, world!") );

Jest to także dobry przykład prostej wtyczki jQuery (setnej).

ern0
źródło
4

Wszystko jest całkiem proste! Oto kilka szybkich przykładów ...


var $example = $( XMLDocRoot );

var $element = $( $example[0].createElement('tag') );
// Note the [0], which is the root

$element.attr({
id: '1',
hello: 'world'
});

var $example.find('parent > child').append( $element );
Niespokojny
źródło
1

Nie wspomniano w poprzednich odpowiedziach, więc dodaję przykładowy przykład tworzenia elementów z najnowszą wersją jQuery, również z dodatkowymi atrybutami, takimi jak zawartość, klasa lub wywołanie zwrotne po kliknięciu:

const mountpoint = 'https://jsonplaceholder.typicode.com/users'

const $button = $('button')
const $tbody = $('tbody')

const loadAndRender = () => {
  $.getJSON(mountpoint).then(data => {

    $.each(data, (index, { id, username, name, email }) => {
      let row = $('<tr>')
        .append($('<td>', { text: id }))
        .append($('<td>', {
          text: username,
          class: 'click-me',
          on: {
            click: _ => {
              console.log(name)
            }
          }
        }))
        .append($('<td>', { text: email }))

      $tbody.append(row)
    })

  })
}

$button.on('click', loadAndRender)
.click-me {
  background-color: lightgrey
}
<table style="width: 100%">
  <thead>
    <tr>
      <th>ID</th>
      <th>Username</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
  
  </tbody>
</table>

<button>Load and render</button>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

Vladislav Ladicky
źródło
-2

jQuery po wyjęciu z pudełka nie ma odpowiednika createElement. W rzeczywistości większość pracy jQuery odbywa się wewnętrznie przy użyciu innerHTML zamiast czystej manipulacji DOM. Jak wspomniano powyżej Adam, w ten sposób można osiągnąć podobne wyniki.

Dostępne są również wtyczki, które wykorzystują DOM przez innerHTML, takie jak appendDOM , DOMEC i FlyDOM, żeby wymienić tylko kilka. Pod względem wydajności natywna jquery jest nadal najbardziej wydajna (głównie dlatego, że używa innerHTML)

James Hughes
źródło
5
Powinieneś być na bieżąco. jQuery nie używa innerHtml, ale analizuje ciąg HTML i wewnętrznie buduje drzewo DOM za pomocą document.createElement (). To jest podstawowy jQuery.
Vincent Robert