.prop () vs .attr ()

2297

Zatem jQuery 1.6 ma nową funkcję prop().

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

czy w tym przypadku robią to samo?

A jeśli ja nie muszę przełączyć się na używanie prop(), wszystkie stare attr()połączenia pęknie jeśli przełączyć do 1,6?

AKTUALIZACJA

selector = '#id'

$(selector).click(function() {
    //instead of:
    var getAtt = this.getAttribute('style');
    //do i use:
    var thisProp = $(this).prop('style');
    //or:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>

(zobacz także to skrzypce: http://jsfiddle.net/maniator/JpUF2/ )

Konsola rejestruje getAttributejako ciąg, a attrjako ciąg, ale propjako CSSStyleDeclaration, Dlaczego? Jak to wpływa na moje kodowanie w przyszłości?

Naftali alias Neal
źródło
17
Będzie to z pewnością interesujące: books.google.ca/…
28
@Neal, ponieważ ta zmiana wykracza poza jQuery. Różnica między atrybutami HTML a właściwościami DOM jest ogromna.
7
Smutno mi, gdy jQuery cofnął zmiany. Kierują się w złym kierunku.
4
@Neal. Tak, a to tylko komplikuje problem zamiast rozdzielać dwie metody.
6
@BritishDeveloper odpowiedź jest bardziej skomplikowana niż zwykłe stwierdzenie, że zawsze używaj x lub y, ponieważ zależy to od tego, co zamierzasz uzyskać. Czy chcesz atrybut, czy chcesz właściwość? to dwie bardzo różne rzeczy.
Kevin B

Odpowiedzi:

1874

Aktualizacja 1 listopada 2012 r

Moja oryginalna odpowiedź dotyczy konkretnie jQuery 1.6. Moja rada pozostaje ta sama, ale jQuery 1.6.1 zmieniło nieco rzeczy: w obliczu przewidywanego stosu uszkodzonych stron zespół jQuery powrócił attr()do czegoś zbliżonego (ale nie dokładnie takiego samego) do swojego starego zachowania dla atrybutów boolowskich . John Resig również pisał o tym na blogu . Widzę trudność, na jakiej się znajdowali, ale nadal nie zgadzam się z jego zaleceniem, by preferować attr().

Oryginalna odpowiedź

Jeśli kiedykolwiek używałeś tylko jQuery, a nie DOM bezpośrednio, może to być myląca zmiana, chociaż zdecydowanie jest to poprawa koncepcyjna. Nie jest to jednak dobre dla bazillionów stron korzystających z jQuery, które zepsują się w wyniku tej zmiany.

Podsumuję główne problemy:

  • Zwykle chcesz prop()raczej niż attr().
  • W większości przypadków prop()robi to , co attr()kiedyś. Wymiana wywołań attr()ze prop()w kodzie generalnie będzie działał.
  • Właściwości są zazwyczaj łatwiejsze w obsłudze niż atrybuty. Wartość atrybutu może być tylko ciągiem, podczas gdy właściwość może być dowolnego typu. Na przykład checkedwłaściwość jest wartością logiczną, stylewłaściwość jest obiektem z indywidualnymi właściwościami dla każdego stylu, sizewłaściwość jest liczbą.
  • Tam, gdzie istnieje zarówno właściwość, jak i atrybut o tej samej nazwie, zwykle aktualizacja jednej spowoduje aktualizację drugiej, ale nie jest tak w przypadku niektórych atrybutów danych wejściowych, takich jak valuei checked: dla tych atrybutów właściwość zawsze reprezentuje bieżący stan, podczas gdy atrybut (z wyjątkiem starych wersji IE) odpowiada domyślnej wartości / sprawdzeniu danych wejściowych (odzwierciedlonej we właściwości defaultValue/ defaultChecked).
  • Ta zmiana usuwa część warstwy magicznego jQuery, która utknęła przed atrybutami i właściwościami, co oznacza, że ​​programiści jQuery będą musieli dowiedzieć się nieco o różnicy między właściwościami a atrybutami. To coś dobrego.

Jeśli jesteś programistą jQuery i cała Twoja firma jest zdezorientowana co do właściwości i atrybutów, musisz cofnąć się o kilka kroków i dowiedzieć się trochę na ten temat, ponieważ jQuery nie stara się już tak bardzo cię chronić przed takimi rzeczami. Autorytatywne , ale nieco suche słowo na ten temat, zawiera specyfikację: DOM4 , HTML DOM , DOM Poziom 2 , DOM Poziom 3 . Dokumentacja DOM Mozilli jest ważna dla większości współczesnych przeglądarek i jest łatwiejsza do odczytania niż specyfikacje, więc może okazać się pomocne odniesienie do niej . Istnieje sekcja dotycząca właściwości elementu .

Jako przykład prostszego w obsłudze właściwości niż atrybutów, rozważ pole wyboru, które jest początkowo zaznaczone. Oto dwa możliwe fragmenty prawidłowego kodu HTML:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

Jak więc sprawdzić, czy pole wyboru jest zaznaczone za pomocą jQuery? Spójrz na Przepełnienie stosu, a zwykle znajdziesz następujące sugestie:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

Jest to właściwie najprostsza rzecz na świecie checkedzwiązana z właściwością Boolean, która istnieje i działa bezbłędnie w każdej głównej przeglądarce skryptowej od 1995 roku:

if (document.getElementById("cb").checked) {...}

Właściwość sprawia, że ​​zaznaczanie lub odznaczanie pola wyboru jest banalne:

document.getElementById("cb").checked = false

W jQuery 1.6 staje się to jednoznacznie

$("#cb").prop("checked", false)

Pomysł użycia checkedatrybutu do skryptowania pola wyboru jest nieprzydatny i niepotrzebny. Właściwość jest tym, czego potrzebujesz.

  • Nie jest oczywiste, jaki jest prawidłowy sposób zaznaczenia lub odznaczenia pola wyboru przy użyciu checkedatrybutu
  • Wartość atrybutu odzwierciedla raczej domyślny niż bieżący stan widoczny (z wyjątkiem niektórych starszych wersji IE, co czyni sprawy jeszcze trudniejszymi). Atrybut nie mówi nic o tym, czy pole wyboru na stronie jest zaznaczone. Zobacz http://jsfiddle.net/VktA6/49/ .
Tim Down
źródło
2
@ TJCrowder, a więc które?
Naftali alias Neal
9
@Neal: Jeśli chcesz wiedzieć, jakie elementy mają właściwości DOM i jak atrybuty mogą zaszczepienia ich wartości, zachować te linki do strony: the DOM2 specyfikację HTML , z DOM2 specyfikację i DOM3 spec. Indeksy w każdym przypadku są doskonałe i prowadzą bezpośrednio do dokładnego opisu nieruchomości, skąd pochodzi jej wartość itp.
TJ Crowder
4
@Neal: Re, co je wyróżnia: źródło i charakter informacji. Spójrz na valueprzykład Tima . Wywołana funkcja attrpobierająca właściwość value zamiast atrybutu „wartość” nie ma większego sensu (i mogą być różne). W przyszłości attrrobienie atrybutów i proprobienie właściwości będzie wyraźniejsze, choć dla niektórych przejście będzie bolesne. Nie bierz tego źle, nie ma nic lepszego niż cofnięcie się i przeczytanie specyfikacji, aby dowiedzieć się, jakie są właściwości.
TJ Crowder
54
@Neal: Element DOM jest obiektem. Właściwości są właściwościami tego obiektu, podobnie jak każdy inny obiekt programujący. Niektóre z tych rekwizytów uzyskują swoje wartości początkowe z atrybutów w znacznikach, które są również przechowywane w obiekcie DOM w osobnej mapie atrybutów. W większości przypadków pisanie na rekwizytach zmienia tylko rekwizyty, chociaż niestety są pewne rekwizyty, które zapisują wszelkie zmiany do bazowego atrybutu ( valuena przykład), ale spróbujmy to zignorować. W 99% przypadków chcesz pracować z rekwizytami. Jeśli musisz pracować z faktycznym atrybutem, prawdopodobnie to wiesz.
TJ Crowder
4
@Tim: „Zmiana valuewłaściwości danych wejściowych nie zmienia ich valueatrybutów we współczesnych przeglądarkach” Nie sądzę, że tak, dlatego zacząłem używać go jako przykładu, ale kiedy zacząłem kodować przykład, kochany jeśli nie został zaktualizowany w Chrome, Firefox, Opera, IE ... - jsbin.com/ahire4 Okazuje się, że to dlatego, że używałeminput[type="button"] do mojego eksperymentu. To nie aktualizuje atrybutu na input[type="text"]- jsbin.com/ahire4/2 Dyskusja o zawiłe !! Nie tylko element, ale jego rodzaj ...
TJ Crowder
664

Myślę, że Tim powiedział to całkiem dobrze , ale cofnijmy się:

Element DOM to obiekt, rzecz w pamięci. Podobnie jak większość obiektów w OOP, ma właściwości . Ma również osobno mapę atrybutów zdefiniowanych na elemencie (zwykle pochodzących ze znaczników czytanych przez przeglądarkę w celu utworzenia elementu). Niektóre właściwości elementu uzyskują swoje wartości początkowe z atrybutów o takich samych lub podobnych nazwach ( valuepobiera swoją wartość początkową z atrybutu „wartość”; hrefpobiera swoją wartość początkową z atrybutu „href”, ale nie jest to dokładnie ta sama wartość; classNamez atrybut „klasa”). Inne właściwości uzyskują swoje wartości początkowe na inne sposoby: Na przykład parentNodewłaściwość uzyskuje swoją wartość na podstawie tego, czym jest jej element nadrzędny;style właściwość, bez względu na to, czy ma atrybut „styl”, czy nie.

Rozważmy tę kotwicę na stronie http://example.com/testing.html:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

Niektóre darmowe grafiki ASCII (i pomijając wiele rzeczy):

+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− +
| HTMLAnchorElement |
+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− +
| href: „http://example.com/foo.html” |
| nazwa: „fooAnchor” |
| id: "fooAnchor" |
| className: "test one" |
| atrybuty: |
| href: "foo.html" |
| nazwa: „fooAnchor” |
| id: "fooAnchor" |
| klasa: „test jeden” |
+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− +

Pamiętaj, że właściwości i atrybuty są różne.

Teraz, mimo że są różne, ponieważ wszystko to ewoluowało, a nie było projektowane od podstaw, szereg właściwości odpisuje na atrybut, z którego pochodzą, jeśli je ustawisz. Ale nie wszyscy tak robią, a jak widać z hrefgóry, mapowanie nie zawsze jest prostym „przekazaniem wartości”, czasem wiąże się to z interpretacją.

Kiedy mówię o właściwościach będących właściwościami obiektu, nie mówię abstrakcyjnie. Oto kod inny niż jQuery:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"

(Wartości te są zgodne z większością przeglądarek; istnieje pewna odmiana).

linkObiekt jest prawdziwa, można zobaczyć tam jest prawdziwa różnica pomiędzy dostępu do własności na niego i uzyskiwania dostępu do atrybutu .

Jak powiedział Tim, przez większość czasu chcemy pracować z nieruchomościami. Częściowo dzieje się tak, ponieważ ich wartości (nawet nazwy) są bardziej spójne w różnych przeglądarkach. Przeważnie chcemy pracować z atrybutami tylko wtedy, gdy nie ma z nim powiązanej właściwości (atrybuty niestandardowe) lub gdy wiemy, że dla tego konkretnego atrybutu atrybut i właściwość nie mają wartości 1: 1 (jak w przypadku href„href” powyżej) .

Standardowe właściwości są określone w różnych specyfikacjach DOM:

Te specyfikacje mają doskonałe indeksy i zalecamy trzymanie linków do nich pod ręką; Używam ich cały czas.

Niestandardowe atrybuty obejmowałyby na przykład wszelkie data-xyzatrybuty, które można umieścić na elementach w celu dostarczenia meta-danych do kodu (teraz jest to ważne od HTML5, o ile trzymasz się data-prefiksu). (Najnowsze wersje jQuery dają ci dostęp do data-xyzelementów za pośrednictwem datafunkcji, ale ta funkcja nie jest tylko akcesorium do data-xyzatrybutów [robi to mniej więcej]; chyba że faktycznie potrzebujesz jej funkcji, użyłbym tej attrfunkcji do interakcji z data-xyzatrybutem).

attrFunkcja używana mieć jakieś zawiłe logiki wokół uzyskanie co myśleli chciałeś, zamiast dosłownie coraz atrybut. To połączyło koncepcje. Przeprowadzka do propi attrmiała na celu ich dezintegrację. Krótko v1.6.0 jQuery poszedł zbyt daleko w tym względzie, ale funkcjonalność dodano szybko z powrotem do attrobsłużyć typowe sytuacje, w których ludzie używają attr, gdy technicznie powinni używać prop.

TJ Crowder
źródło
Łał. ta nowa aktualizacja 1.6.1 naprawdę trochę unieważnia to pytanie .. (ale niewiele), ale ten link w zasadzie teraz odpowiada na to pytanie
Naftali alias Neal
Nie unieważniłem go, po prostu naprawiłem błąd za pomocą jquery1.7, w którym ustawiałem .attr („klasa”, „bla”) i nie działało tam .prop („className”, „bla” ) pracował
PandaWood,
@PandaWood: .attr('class', 'bla')działa zgodnie z oczekiwaniami w wersjach 1.7.0 , 1.7.1 i 1.7.2 w Chrome 17, Firefox 11, Opera 11, IE6, IE8, IE9 i Safari 5.
TJ Crowder
Dzięki, musi być coś konkretnego w moim przypadku, pozwól mi to sprawdzić i wrócić z przypadkiem testowym. Ale zmiana obecnego kodu, tak aby po prostu „prop / className” zamiast „attr” naprawiała dla nas ogromny błąd, który pojawił się po przejściu z jquery 1.4 na 1.7 - we wszystkich przeglądarkach
PandaWood
3
@TJCrowder re: .data- odczyta domyślną wartość atrybutu, jeśli jest obecny, ale jeśli napiszesz do niego, zmieni ukrytą właściwość elementu i nie zaktualizuje atrybutu.
Alnitak,
250

Ta zmiana długo czekała na jQuery. Przez lata byli zadowoleni z funkcji o nazwie, attr()która w większości pobierała właściwości DOM, a nie wynik, którego można oczekiwać od nazwy. Segregacja attr()i prop()powinna pomóc złagodzić pewne zamieszanie między atrybutami HTML a właściwościami DOM. $.fn.prop()pobiera określoną właściwość DOM, a $.fn.attr()pobiera określony atrybut HTML.

Aby w pełni zrozumieć, jak działają, oto obszerne wyjaśnienie różnicy między atrybutami HTML a właściwościami DOM:

Atrybuty HTML

Składnia:

<body onload="foo()">

Cel: umożliwia znacznikom powiązanie z nimi danych na potrzeby zdarzeń, renderowania i innych celów.

Wizualizacja: Atrybuty HTML Atrybut klasy jest pokazany tutaj na ciele. Jest dostępny poprzez następujący kod:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

Atrybuty są zwracane w postaci ciągów i mogą być niespójne między przeglądarkami. Mogą być jednak niezbędne w niektórych sytuacjach. Jak pokazano powyżej, IE Quirks Mode (i poniżej) oczekuje nazwy właściwości DOM w get / set / removeAttribute zamiast nazwy atrybutu. Jest to jeden z wielu powodów, dla których ważna jest znajomość różnicy.

Właściwości DOM

Składnia:

document.body.onload = foo;

Cel: Daje dostęp do właściwości należących do węzłów elementu. Te właściwości są podobne do atrybutów, ale są dostępne tylko przez JavaScript. Jest to ważna różnica, która pomaga wyjaśnić rolę właściwości DOM. Należy pamiętać, że atrybuty różnią się całkowicie od właściwości , ponieważ to przypisanie procedury obsługi zdarzeń jest bezużyteczne i nie odbierze zdarzenia (ciało nie ma zdarzenia onload, tylko atrybut onload).

Wyobrażanie sobie: Właściwości DOM

Tutaj zobaczysz listę właściwości w zakładce „DOM” w Firebug. To są właściwości DOM. Od razu zauważysz sporo z nich, ponieważ używałeś ich wcześniej, nie wiedząc o tym. Ich wartości są tym, co otrzymasz za pośrednictwem JavaScript.

Dokumentacja

Przykład

HTML: <textarea id="test" value="foo"></textarea>

JavaScript: alert($('#test').attr('value'));

We wcześniejszych wersjach jQuery zwraca pusty ciąg. W pkt 1.6, zwraca właściwą wartość foo.

Nie patrząc na nowy kod żadnej z funkcji, mogę z całą pewnością stwierdzić, że zamieszanie ma więcej wspólnego z różnicą między atrybutami HTML a właściwościami DOM, niż z samym kodem. Mam nadzieję, że to wyjaśniło ci kilka rzeczy.

-Matt

K.Dᴀᴠɪs
źródło
7
$.prop()pobiera właściwości DOM, $.attr()pobiera atrybuty HTML. Próbuję psychicznie wypełnić lukę, abyście mogli zrozumieć różnicę między nimi.
10
Chłopcze, też jestem teraz zmieszany. Więc $('#test').prop('value')nic nie zwraca? Nie dotyczy .attr('checked')też pola wyboru? Ale kiedyś tak było? Teraz musiałbyś to zmienić prop('checked')? Nie rozumiem potrzeby takiego rozróżnienia - dlaczego ważne jest rozróżnienie atrybutów HTML i właściwości DOM? Jaki jest typowy przypadek użycia, który sprawił, że ta zmiana „nadchodzi długo” ? Co jest złego w wyodrębnianiu rozróżnienia między nimi dwoma, ponieważ wydaje się, że ich przypadki użycia w większości się pokrywają?
BlueRaja - Danny Pflughoeft
5
@BlueRaja: ponieważ istnieje poważna różnica między tymi dwiema koncepcjami, która, jeśli szczotkujesz go pod dywan, jak kiedyś jQuery, powoduje nieoczekiwane niepowodzenia. valuejest jednym z najbardziej oczywistych przypadków, ponieważ valuewłaściwość poda ci bieżącą wartość pola, ale valueatrybut da ci oryginalną wartość zadeklarowaną w value="..."atrybucie, która w rzeczywistości jest defaultValuewłaściwością. (Chociaż ten konkretny przypadek znów jest mylony przez błędy w IE <9.)
Bobin
4
@BlueRaja: Odpowiedź na to pytanie jest jeszcze bardziej skomplikowana. :-) Ustawienie attr('value', ...)w jQuery <1.6 ustawia właściwość, więc bieżąca wartość się zmienia, a wartość domyślna nie. W 1.6 ustawia atrybut, więc teoretycznie wartość domyślna zmienia się, a wartość bieżąca nie. Istnieją jednak (więcej) niespójności przeglądarki dotyczące tego, co dokładnie valuerobi ustawienie tego atrybutu. W IE ustawia również bieżącą wartość; w niektórych przeglądarkach ustawia bieżącą wartość tylko wtedy, gdy bieżąca wartość nie była wcześniej ustawiana. [płacze]
bobince
1
Podobnie jak powiedział @Quentin: „Atrybuty są definiowane przez HTML. Właściwości są definiowane przez DOM”. Najprostsza wersja, którą przeczytałem.
Alan Dong
240

Właściwość znajduje się w DOM; atrybut znajduje się w HTML, który jest analizowany w DOM.

Dalsze szczegóły

Jeśli zmienisz atrybut, zmiana zostanie odzwierciedlona w DOM (czasem pod inną nazwą).

Przykład: zmiana classatrybutu znacznika spowoduje zmianę classNamewłaściwości tego znacznika w DOM. Jeśli nie masz atrybutu w znaczniku, nadal masz odpowiednią właściwość DOM z pustą lub domyślną wartością.

Przykład: Chociaż tag nie ma classatrybutu, właściwość DOM classNameistnieje z pustą wartością ciągu.

edytować

Jeśli zmienisz jedno, drugie zostanie zmienione przez kontroler i odwrotnie. Ten kontroler nie znajduje się w jQuery, ale w natywnym kodzie przeglądarki.

Junzen
źródło
Czy to oznacza, że ​​lepiej zaktualizować atrybut, ponieważ wtedy upewniasz się, że atrybut i właściwość zostały zaktualizowane i są wyrównane?
Łukasz
1
@Luke DOM to wewnętrzna reprezentacja techniczna, model. Atrybuty HTML są zewnętrzną reprezentacją, widokiem. Jeśli zmienisz jedno, drugie zostanie zmienione przez kontroler i odwrotnie.
Junzen
@HerrSerker Więc oba są zsynchronizowane przez kontroler? Zakładam, że jest to tylko metoda attr i prop jQuery? Oto modyfikacja twojego skrzypka, gdzie eksploruję to więcej - jsfiddle.net/v8wRy - i do tej pory wydają się być równoważne.
Łukasz
3
„Jeśli zmienisz jeden, drugi zostanie zmieniony przez kontroler i odwrotnie. Ten kontroler nie znajduje się w jQuery, ale w natywnym kodzie przeglądarki.” Nie dotyczy to większości atrybutów / właściwości. Dla większości jest to tylko tłumaczenie jednostronne, w którym atrybut określa wartość początkową odpowiedniej właściwości. Dwie pierwsze odpowiedzi szczegółowo to wyjaśniają.
ᴠɪɴᴄᴇɴᴛ
@Vincent. Nie rozumiem, gdzie dwie pierwsze odpowiedzi mówią coś sprzecznego z moją odpowiedzią. Oczywiście większość atrybutów to wartości początkowe odpowiednich właściwości DOM. Ale są od siebie zależne. Wypróbuj coś takiego jak jQuery('p').prop('className', 'foo');w konsoli Chrome, a zobaczysz, jak każdy akapit otrzymuje classatrybut thg 'foo'. Oczywiście nie ma go w kodzie źródłowym, który pochodzi z serwera. To jest stałe.
Junzen
140

To tylko rozróżnienie między atrybutami HTML a obiektami DOM powoduje zamieszanie. Dla tych, którzy czują się komfortowo, działając na elementach DOM właściwości natywne, takie jak this.src this.value this.checkeditp, .propjest bardzo ciepłym przyjęciem dla rodziny. Dla innych jest to tylko dodatkowa warstwa zamieszania. Wyjaśnijmy to.

Najłatwiejszym sposobem sprawdzenia różnicy między .attri .propjest następujący przykład:

<input blah="hello">
  1. $('input').attr('blah'): zwraca 'hello'zgodnie z oczekiwaniami. Tu nie ma niespodzianek.
  2. $('input').prop('blah'): zwraca undefined- ponieważ próbuje to zrobić [HTMLInputElement].blah- i nie istnieje taka właściwość dla tego obiektu DOM. Istnieje tylko w zakresie jako atrybut tego elementu, tj[HTMLInputElement].getAttribute('blah')

Teraz zmieniamy kilka takich rzeczy:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): zwraca 'apple'eh? Dlaczego nie „gruszka”, ponieważ ustawiono ją ostatnio na tym elemencie. Ponieważ właściwość została zmieniona na atrybucie wejściowym, a nie na samym elemencie wejściowym DOM - w zasadzie działają prawie niezależnie od siebie.
  2. $('input').prop('blah'): zwroty 'pear'

Rzeczy, na które naprawdę musisz uważać, to po prostu nie mieszaj ich użycia dla tej samej właściwości w całej aplikacji z powyższego powodu.

Zobacz skrzypce demonstrujące różnicę: http://jsfiddle.net/garreh/uLQXc/


.attrvs .prop:

Runda 1: styl

<input style="font:arial;"/>
  • .attr('style') - zwraca style wbudowane dla dopasowanego elementu tj "font:arial;"
  • .prop('style') - zwraca obiekt deklaracji stylu tj CSSStyleDeclaration

Runda 2: wartość

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
  • .attr('value')- zwraca 'hello'*
  • .prop('value') -- zwroty 'i changed the value'

* Uwaga: jQuery z tego powodu ma .val()metodę, która wewnętrznie jest równoważna.prop('value')

Gary Green
źródło
@Neal, ponieważ lepiej odnosi się do struktury funkcji jquery. „$ ('input'). prop ('blah'): zwraca niezdefiniowane - ponieważ próbuje zrobić [HTMLInputElement] .blah - i nie ma takiej właściwości w tym obiekcie DOM. Istnieje tylko w zakresie jako atrybut tego elementu, tj. [HTMLInputElement] .getAttribute („blah”) ”
Uğur Gümüşhan
2
Wygląda na to, że różni się od doc, api.jquery.com/prop : "Należy ustawić metodę .prop (), aby ustawić wyłączoną i sprawdzoną zamiast metody .attr (). Do uzyskania i należy użyć metody .val () wartość ustawienia. ”
łabędź
53

TL; DR

Użyj prop()ciągu attr()w większości przypadków.

Nieruchomość jest obecny stan elementu wejściowego. Atrybut jest wartością domyślną.

Właściwość może zawierać rzeczy różnych typów. Atrybut może zawierać tylko ciągi znaków

agjmills
źródło
1
jeśli to możliwe, przyjdź z kilkoma prostymi próbkami tego, co mówisz, a także pokaż, kiedy używać prop() and when to go for attr(). czekam na odpowiedź :)
Mou
36

Brudna kratka

Ta koncepcja stanowi przykład, w którym można zaobserwować różnicę: http://www.w3.org/TR/html5/forms.html#concept-input-checked-dirty

Wypróbuj to:

  • naciśnij przycisk. Oba pola wyboru zostały zaznaczone.
  • odznacz oba pola wyboru.
  • kliknij przycisk ponownie. Zaznaczono tylko pole propwyboru. HUK!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>

Na niektóre atrybuty jak disabledna buttondodanie lub usunięcie atrybutu content disabled="disabled"zawsze przełącza własność (tzw atrybut IDL w HTML5), ponieważ http://www.w3.org/TR/html5/forms.html#attr-fe-disabled mówi:

Wyłączony atrybut IDL musi odzwierciedlać atrybut wyłączonej treści.

więc możesz sobie z tym poradzić, chociaż jest brzydka, ponieważ modyfikuje HTML bez potrzeby.

W przypadku innych atrybutów, takich jak checked="checked"on input type="checkbox", rzeczy się psują, ponieważ po kliknięciu stają się one brudne, a następnie dodanie lub usunięcie checked="checked"atrybutu content nie przełącza już sprawdzania .

Dlatego powinieneś używać głównie .prop, ponieważ wpływa to bezpośrednio na efektywną właściwość, zamiast polegać na złożonych skutkach ubocznych modyfikacji HTML.

Ciro Santilli
źródło
Aby uzyskać kompletność, wypróbuj również następujące odmiany: 1) Przed kliknięciem przycisku zaznacz, a następnie odznacz pierwsze pole wyboru 2) (W tym przypadku musisz zmienić fragment checkedchecked="checked"
kodu
33

Wszystko jest w dokumencie :

Różnica między atrybutami i właściwościami może być ważna w określonych sytuacjach. Przed wersją jQuery 1.6 metoda .attr () czasami uwzględniała wartości właściwości przy pobieraniu niektórych atrybutów, co może powodować niespójne zachowanie. Począwszy od jQuery 1.6, metoda .prop () umożliwia jawne pobieranie wartości właściwości, podczas gdy .attr () pobiera atrybuty.

Więc użyj prop!

Arnaud F.
źródło
2
To oznacza, że ​​kiedy przejdę na 1.6, wiele rzeczy się zepsuje?
Naftali alias Neal
Nie, to tylko niespójne zachowanie, jeśli zadziała wcześniej, zawsze będzie działać z jQuery 1.6, po prostu śmigło jest bezpieczniejsze;)
Arnaud F.
6
Wydaje mi się, że pamiętam. $.attr()pobieranie właściwości przez większość czasu z nim pracowałem, a nie „czasami”. Powstałe z tego powodu zamieszanie jest nadal rezonansowe. Niestety mam problem ze znalezieniem ostatecznego odczytania atrybutów HTML vs. właściwości DOM, więc mogę tu napisać odpowiedź.
3
@ Arnaud-f Nieprawda. Cały kod wcześniejszy niż 1.6, który używa attr („zaznaczone”) do zaznaczenia pól wyboru, będzie teraz uszkodzony.
CaptSaltyJack
3
@Matt McDonald: Jaki masz na myśli „... problem ze znalezieniem ostatecznego odczytu atrybutów HTML vs. właściwości DOM ...”? Właściwości (odzwierciedlone i inne) są opisane w specyfikacji HTML DOM2 ; być może trzeba zajrzeć do specyfikacji DOM2 i DOM3 .
TJ Crowder
28

atrybuty znajdują się w dokumencie / pliku tekstowym HTML (== wyobraź sobie, że jest to wynik analizowanego znacznika HTML), podczas gdy
właściwości są w drzewie DOM HTML (== w zasadzie faktyczna właściwość jakiegoś obiektu w sensie JS).

Co ważne, wiele z nich jest zsynchronizowanych (jeśli zaktualizujesz classwłaściwość, classatrybut w HTML również zostanie zaktualizowany; w przeciwnym razie). Ale niektóre atrybuty mogą być zsynchronizowane z nieoczekiwanymi właściwościami - np. Atrybut checked odpowiada właściwości defaultChecked , więc

  • ręczne zaznaczenie pola wyboru zmieni .prop('checked')wartość, ale nie zmieni .attr('checked')i .prop('defaultChecked')wartości
  • ustawienie $('#input').prop('defaultChecked', true)również się zmieni .attr('checked'), ale nie będzie to widoczne na elemencie.

Ogólna zasada brzmi : .prop()należy stosować metodę dla atrybutów / właściwości boolowskich oraz dla właściwości, które nie istnieją w html (takich jak window.location). Wszystkie pozostałe atrybuty (te, które można zobaczyć w pliku HTML) mogą i powinny być nadal modyfikowane przy użyciu tej .attr() metody. ( http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/ )

A oto tabela, która pokazuje, gdzie .prop()jest preferowana (mimo że .attr()nadal może być używana).

stół z preferowanym użyciem


Dlaczego czasami miałbyś chcieć używać .prop () zamiast .attr (), gdy jest to oficjalnie zalecane?

  1. .prop()może zwrócić dowolny typ - ciąg znaków, liczbę całkowitą, wartość logiczną; podczas gdy .attr()zawsze zwraca ciąg.
  2. .prop()mówi się, że jest około 2,5 razy szybszy niż .attr().
jeziora
źródło
coś zostało zmienione, takie jak: $('#myImageId').prop('src', 'http://example.com/img.png'), var class = $('.myDivClass').prop('class'), lub $('#myTextBox').prop('type', 'button'). I tak dalej ...
@ Mr.Wolf, przepraszam, nie rozumiem o co ci chodzi. co się zmieniło'? składnia zawsze taka była.
jeziora
Myślę, że tabela w twojej odpowiedzi jest niepotrzebna. Ponieważ .prop()działa dobrze ze wszystkimi właściwościami. Nie chcesz zaznaczyć wszystkich właściwości w .prop()kolumnie, prawda?
@ Mr.Wolf, myślę, że jest to konieczne, ponieważ, jak już wspomniano, „pokazuje, gdzie .prop()jest preferowane (choć .attr()nadal można go używać)”
jeziora
Zwykle używam .attr()do zdefiniowania zdarzenia, które .prop()nie może. Tak: $('.myDiv').attr('onclick', 'alert("Hello world!")'). Jeśli zmienisz .attr()na .prop(), to nie będzie działać. Uważam, że nie ma powodu, aby używać .attr()lub ustawiać wartość id/class/href/checked/src...... Zauważ, że nie mówię, że się mylisz.
20

.attr():

  • Uzyskaj wartość atrybutu dla pierwszego elementu w zestawie dopasowanych elementów.
  • Podaje wartość elementu taką, jaka została zdefiniowana w html podczas ładowania strony

.prop():

  • Uzyskaj wartość właściwości pierwszego elementu w zestawie pasujących elementów.
  • Podaje zaktualizowane wartości elementów, które są modyfikowane przez javascript / jquery
Kgn-web
źródło
13

Zwykle będziesz chciał użyć właściwości. Użyj atrybutów tylko dla:

  1. Uzyskiwanie niestandardowego atrybutu HTML (ponieważ nie jest on synchronizowany z właściwością DOM).
  2. Uzyskiwanie atrybutu HTML, który nie jest synchronizowany z właściwością DOM, np. Uzyskanie „oryginalnej wartości” standardowego atrybutu HTML, np <input value="abc">.
naor
źródło
7

attributes -> HTML

properties -> DOM

NkS
źródło
8
Wiem, co chcesz powiedzieć, ale HTML to język znaczników, a DOM reprezentacja utworzona z HTML. DOMElement ma zarówno atrybuty, jak i właściwości .
t.niese
@ t.niese, attirbutesrównież jedna z własnościDOM
NkS
Krótka odpowiedź jest prosta.
Nabi KAZ
6

Przed wersją jQuery 1.6 attr()metoda czasami uwzględniała wartości właściwości przy pobieraniu atrybutów, co powodowało dość niespójne zachowanie.

Wprowadzenie prop()metody umożliwia jawne pobieranie wartości właściwości podczas .attr()pobierania atrybutów.

Dokumenty:

jQuery.attr() Uzyskaj wartość atrybutu dla pierwszego elementu w zestawie dopasowanych elementów.

jQuery.prop() Uzyskaj wartość właściwości pierwszego elementu w zestawie pasujących elementów.

Gothburz
źródło
3

Delikatnie przypomnij o użyciu prop(), na przykład:

if ($("#checkbox1").prop('checked')) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Powyższa funkcja służy do sprawdzania, czy pole wyboru 1 jest zaznaczone, czy nie, jeśli zaznaczone: return 1; jeśli nie: zwraca 0. Funkcja prop () użyta tutaj jako funkcja GET.

if ($("#checkbox1").prop('checked', true)) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Powyższa funkcja służy do ustawienia pola wyboru 1 do sprawdzenia i ZAWSZE zwraca 1. Teraz funkcja prop () jest używana jako funkcja SET.

Nie zadzieraj.

P / S: Kiedy sprawdzam właściwość Image src . Jeśli src jest pusty, prop zwróć bieżący adres URL strony (nieprawidłowy), a attr zwróć pusty ciąg (prawy).

użytkownik2657778
źródło
Mylisz się w tym przykładzie: <img src="smiley.gif" alt="Smiley face" width="42" height="42" onclick="alert($(this).prop('src'))">. Powinien działać i zwrócić lokalizację obrazu.
2

Jedno .attr()może zrobić, .prop()czego nie można: wpłynąć na selektory CSS

Oto problem, którego nie widziałem w innych odpowiedziach.

Selektor CSS [name=value]

  • odpowie na .attr('name', 'value')
  • ale nie zawsze .prop('name', 'value')

.prop() wpływa tylko na kilka selektorów atrybutów

.attr() wpływa na wszystkie selektory atrybutów

Bob Stein
źródło
0

1) Właściwość znajduje się w DOM; atrybut znajduje się w HTML, który jest analizowany w DOM.

2) $ (elem) .attr („zaznaczony”) (1.6.1+) „zaznaczony” (ciąg) Zmieni się ze stanem pola wyboru

3) $ (elem) .attr („zaznaczony”) (przed 1.6) true (Boolean) Zmieniono ze stanem pola wyboru

  • Głównie chcemy użyć dla obiektu DOM, a nie niestandardowego atrybutu, takiego jak data-img, data-xyz.

  • Również niektóre różnice podczas uzyskiwania dostępu do checkboxwartości oraz href z attr()i prop()jako rzecz zmieniają się z wyjściem DOM z prop()pełnym linkiem origini Booleanwartością pola wyboru (pre-1.6)

  • Możemy uzyskać dostęp do elementów DOM tylko z propinnymi, niż to dajeundefined

Parth Trivedi
źródło
0

Istnieje kilka innych uwag w prop () vs attr ():

  • selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked i defaultSelected..etc należy pobrać i ustawić za pomocą metody .prop (). Nie mają one odpowiednich atrybutów i są jedynie właściwościami.

  • Pole wyboru typu danych wejściowych

       .attr('checked') //returns  checked
       .prop('checked') //returns  true
       .is(':checked') //returns true
  • metoda prop zwraca wartość logiczną dla zaznaczonego, wybranego, wyłączonego, readOnly..etc, natomiast attr zwraca zdefiniowany ciąg. Możesz więc bezpośrednio użyć .prop („zaznaczone”) w warunku if.

  • .attr () wywołuje wewnętrznie .prop (), więc metoda .attr () będzie nieco wolniejsza niż bezpośredni dostęp do nich poprzez .prop ().

Rishu Ranjan
źródło
-2

Odpowiedź Gary'ego Hole'a jest bardzo istotna dla rozwiązania problemu, jeśli kod jest napisany w taki sposób

obj.prop("style","border:1px red solid;")

Ponieważ obiekt prop zwraca CSSStyleDeclarationobiekt, powyższy kod nie będzie działał poprawnie w niektórych przeglądarkach (testowane zIE8 with Chrome Frame Plugin w moim przypadku ).

W ten sposób zmieniamy go w następujący kod

obj.prop("style").cssText = "border:1px red solid;"

Rozwiązać problem.

zawhtut
źródło