Vraag .prop () vs .attr ()


Zo jQuery 1.6 heeft de nieuwe functie prop().

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

of doen ze in dit geval hetzelfde?

En als ik do moet overschakelen op gebruik prop(), al het oude attr() oproepen zullen breken als ik overschakelen naar 1.6?

BIJWERKEN

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>

(zie ook deze viool: http://jsfiddle.net/maniator/JpUF2/)

De console logt het getAttribute als een string, en de attr als een string, maar de prop als een CSSStyleDeclaration, Waarom? En hoe beïnvloedt dat in de toekomst mijn codering?


2053
2018-05-03 19:33


oorsprong


antwoorden:


Update 1 november 2012

Mijn oorspronkelijke antwoord is specifiek van toepassing op jQuery 1.6. Mijn advies is hetzelfde gebleven, maar jQuery 1.6.1 veranderde iets: in het licht van de voorspelde stapel gebroken websites, het jQuery-team teruggekeerd attr() naar iets dicht bij (maar niet precies hetzelfde als) zijn oude gedrag voor Booleaanse attributen. John Resig ook erover geblogd. Ik kan de moeilijkheid zien waarin ze zich bevonden, maar ben het nog steeds oneens met de aanbeveling om de voorkeur te geven attr().

Origineel antwoord

Als je jQuery en niet rechtstreeks de DOM hebt gebruikt, zou dit een verwarrende verandering kunnen zijn, hoewel het conceptueel beslist een verbetering is. Niet zo goed voor de baziljoenen van sites die jQuery gebruiken en die als gevolg van deze wijziging breken.

Ik zal de belangrijkste kwesties samenvatten:

  • Meestal wil je dat prop() liever dan attr().
  • In de meeste gevallen prop() doet wat attr() gewend te doen. Gesprekken vervangen naar attr() met prop() in uw code zal over het algemeen werken.
  • Eigenschappen zijn over het algemeen eenvoudiger om mee om te gaan dan attributen. Een attribuutwaarde mag alleen een tekenreeks zijn, terwijl een eigenschap van elk type kan zijn. Bijvoorbeeld de checked eigenschap is een Boolean, de style eigenschap is een object met individuele eigenschappen voor elke stijl, de size eigendom is een nummer.
  • Wanneer zowel een eigenschap als een attribuut met dezelfde naam bestaat, zal het bijwerken van de ene gewoonlijk de andere bijwerken, maar dit is niet het geval voor bepaalde kenmerken van invoer, zoals value en checked: voor deze kenmerken vertegenwoordigt de eigenschap altijd de huidige status terwijl het kenmerk (behalve in oude versies van IE) overeenkomt met de standaardwaarde / checkedness van de invoer (weerspiegeld in de defaultValue / defaultChecked eigendom).
  • Deze wijziging verwijdert een deel van de laag magische jQuery die voor attributen en eigenschappen vastzit, wat betekent dat ontwikkelaars van jQuery een beetje moeten leren over het verschil tussen eigenschappen en attributen. Dit is iets goeds.

Als je een jQuery-ontwikkelaar bent en door dit hele bedrijf wordt verward over eigenschappen en kenmerken, moet je een stapje terug doen en er iets over leren, aangezien jQuery niet langer zo hard probeert je tegen dit soort dingen te beschermen. Voor het gezaghebbende maar ietwat droge woord over dit onderwerp, zijn er de specificaties: DOM4, HTML DOM, DOM-niveau 2, DOM-niveau 3. De DOM-documentatie van Mozilla is geldig voor de meeste moderne browsers en is gemakkelijker te lezen dan de specificaties, dus je kunt ze vinden DOM-referentie nuttig. Er is een sectie over elementeigenschappen.

Als een voorbeeld van hoe eigenschappen eenvoudiger te hanteren zijn dan attributen, overweeg dan een selectievakje aanvankelijk aangevinkt. Hier zijn twee mogelijke stukjes geldige HTML om dit te doen:

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

Dus, hoe kom je erachter of het selectievakje is aangevinkt met jQuery? Kijk naar Stack Overflow en je zult vaak de volgende suggesties tegenkomen:

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

Dit is eigenlijk het eenvoudigste wat ter wereld te maken heeft met de checked Boolean-eigenschap, die sinds 1995 foutloos in elke grote script-browser bestaat en werkte:

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

De eigenschap maakt ook het in- of uitschakelen van het selectievakje triviaal:

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

In jQuery 1.6 wordt dit ondubbelzinnig

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

Het idee om de checked attribuut voor het scripten van een selectievakje is nutteloos en onnodig. De woning is wat je nodig hebt.

  • Het is niet duidelijk wat de juiste manier is om het selectievakje in of uit te schakelen, met behulp van de checked attribuut
  • De kenmerkwaarde weerspiegelt de standaardwaarde in plaats van de huidige zichtbare staat (behalve in sommige oudere versies van IE, waardoor het nog moeilijker wordt). Het attribuut vertelt u niets over het feit of het selectievakje op de pagina is aangevinkt. Zien http://jsfiddle.net/VktA6/49/.

1734
2018-05-03 23:06



I denk Tim zei het vrij goed, maar laten we een stapje terug doen:

Een DOM-element is een object, een ding in het geheugen. Zoals de meeste objecten in OOP, wel eigenschappen. Het heeft ook, afzonderlijk, een kaart met de kenmerken die op het element zijn gedefinieerd (meestal afkomstig van de markup die de browser heeft gelezen om het element te maken). Sommige van de elementen eigenschappen haal hun eerste waarden van attributen met dezelfde of soortgelijke namen (value krijgt de beginwaarde van het kenmerk "value"; href krijgt de beginwaarde van het kenmerk 'href', maar het is niet precies dezelfde waarde; className van het kenmerk "klasse"). Andere eigenschappen krijgen hun beginwaarden op andere manieren: bijvoorbeeld de parentNode eigenschap krijgt zijn waarde op basis van wat het bovenliggende element is; een element heeft altijd een style eigenschap, of deze nu een kenmerk "style" heeft of niet.

Laten we dit anker in een pagina bekijken http://example.com/testing.html:

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

Enige gratis ASCII-kunst (en veel spullen weglaten):

+ ------------------------------------------- +
| HTMLAnchorElement |
+ ------------------------------------------- +
| href: "http://example.com/foo.html" |
| naam: "fooAnchor" |
| id: "fooAnchor" |
| className: "test één" |
| attributen: |
| href: "foo.html" |
| naam: "fooAnchor" |
| id: "fooAnchor" |
| klas: "test een" |
+ ------------------------------------------- +

Merk op dat de eigenschappen en attributen verschillend zijn.

Hoewel ze verschillend zijn, omdat dit allemaal is geëvolueerd in plaats van vanaf de grond af te zijn ontworpen, schrijven een aantal eigenschappen terug naar het attribuut waarvan ze zijn afgeleid als je ze hebt ingesteld. Maar niet allemaal, en zoals je kunt zien hrefhierboven is de toewijzing niet altijd een straight "geef de waarde door", soms is er sprake van interpretatie.

Als ik het heb over eigenschappen als eigenschappen van een object, spreek ik niet in abstracto. Hier is wat niet-jQuery-code:

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

(Deze waarden zijn van de meeste browsers, er is wat variatie.)

De link object is echt, en je kunt zien dat er een echt verschil is tussen toegang tot een eigendom erop en toegang tot een attribuut.

Zoals Tim zei, de grote meerderheid van de tijd willen we met eigenschappen werken. Gedeeltelijk komt dat omdat hun waarden (zelfs hun namen) over het algemeen consistenter zijn in browsers. We willen meestal alleen met attributen werken als er geen eigenschap aan is gerelateerd (aangepaste attributen), of als we weten dat voor dat specifieke attribuut het attribuut en de eigenschap niet 1: 1 zijn (zoals bij href en "href" hierboven).

De standaard eigenschappen zijn uiteengezet in de verschillende DOM-specificaties:

Deze specificaties hebben uitstekende indexen en ik raad aan om links naar hen bij de hand te houden; Ik gebruik ze altijd.

Aangepaste kenmerken kunnen bijvoorbeeld elk zijn data-xyz attributen die u op elementen kunt plaatsen om metagegevens aan uw code te verstrekken (nu dat geldig is vanaf HTML5, zolang u zich aan de data- voorvoegsel). (Recente versies van jQuery geven u toegang tot data-xyz elementen via de data functie, maar die functie is niet gewoon een accessor voor data-xyz attributen [het doet zowel meer als minder dan dat]; tenzij je de functies echt nodig hebt, zou ik de attr functie om mee te werken data-xyz attribuut.)

De attr De functie had enige ingewikkelde logica om te krijgen wat ze dachten dat je wilde, in plaats van letterlijk het attribuut te krijgen. Het bracht de concepten samen. Verhuizen naar prop en attr was bedoeld om ze te deblokkeren. Kort gezegd in v1.6.0 ging jQuery in dat opzicht te ver, maar met functionaliteit werd snel terug toegevoegd naar attr om de veel voorkomende situaties te hanteren waar mensen gebruik van maken attr wanneer ze technisch gezien zouden moeten gebruiken prop.


621
2018-05-04 14:27



Deze verandering is lang aan de gang voor jQuery. Al jaren zijn ze tevreden met een functie met de naam attr() die meestal DOM-eigenschappen heeft opgehaald, niet het resultaat dat je van de naam zou verwachten. De segregatie van attr() en prop() moet een deel van de verwarring tussen HTML-kenmerken en DOM-eigenschappen helpen verlichten. $.fn.prop() pakt de opgegeven DOM-eigenschap terwijl $.fn.attr() pakt het opgegeven HTML-kenmerk.

Om volledig te begrijpen hoe ze werken, vindt u hier een uitgebreide uitleg over het verschil tussen HTML-kenmerken en DOM-eigenschappen .:

HTML-kenmerken

Syntaxis:

<body onload="foo()">

Doel: Toestaan ​​dat markeringen gegevens bevatten die eraan zijn gekoppeld voor evenementen, weergave en andere doeleinden.

visualisatie: HTML AttributesHet kenmerk class wordt hier weergegeven op de body. Het is toegankelijk via de volgende code:

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

Attributen worden geretourneerd in stringvorm en kunnen van browser tot browser niet consistent zijn. In sommige situaties kunnen ze echter van levensbelang zijn. Zoals hierboven geïllustreerd, verwacht IE 8 Quirks Mode (en hieronder) de naam van een DOM-eigenschap in get / set / removeAttribute in plaats van de kenmerknaam. Dit is een van de vele redenen waarom het belangrijk is om het verschil te kennen.

DOM-eigenschappen

Syntaxis:

document.body.onload = foo;

Doel: Geeft toegang tot eigenschappen die behoren tot elementknooppunten. Deze eigenschappen zijn vergelijkbaar met kenmerken, maar zijn alleen toegankelijk via JavaScript. Dit is een belangrijk verschil dat de rol van DOM-eigenschappen verduidelijkt. Houd er rekening mee dat attributen compleet verschillen van eigenschappen, omdat deze toewijzing van de gebeurtenishandler nutteloos is en de gebeurtenis niet ontvangt (instantie heeft geen onload-gebeurtenis, alleen een onload-attribuut).

visualisatie: DOM Properties

Hier ziet u een lijst met eigenschappen onder het tabblad "DOM" in Firebug. Dit zijn DOM-eigenschappen. Je zult er meteen een paar opmerken, omdat je ze eerder hebt gebruikt zonder het te weten. Hun waarden zijn wat u ontvangt via JavaScript.

Documentatie

Voorbeeld

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

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

In eerdere versies van jQuery retourneert dit een lege tekenreeks. In 1.6 wordt de juiste waarde geretourneerd, foo.

Zonder de nieuwe code voor beide functies te hebben bekeken, kan ik met vertrouwen zeggen dat de verwarring meer te maken heeft met het verschil tussen HTML-kenmerken en DOM-eigenschappen dan met de code zelf. Hopelijk heeft dit wat voor je opgeruimd.

-Mat


234
2018-05-03 20:05



Een eigenschap bevindt zich in de DOM; een attribuut is in de HTML die in de DOM is geparseerd.

Verdere details

Als u een kenmerk wijzigt, wordt de wijziging weergegeven in de DOM (soms met een andere naam).

Voorbeeld: de. Wijzigen class attribuut van een tag zal de className eigendom van die tag in de DOM. Als u geen kenmerk op een tag hebt, heeft u nog steeds de bijbehorende DOM-eigenschap met een lege of standaardwaarde.

Voorbeeld: terwijl uw tag nee heeft class attribuut, de eigenschap DOM className bestaat met een lege reekswaarde.

Bewerk

Als u de ene wijzigt, wordt de andere gewijzigd door een controller en omgekeerd. Deze controller bevindt zich niet in jQuery, maar in de native code van de browser.


232
2017-09-27 16:55



Het is gewoon het verschil tussen HTML-kenmerken en DOM-objecten die voor verwarring zorgen. Voor diegenen die zich op hun gemak voelen met de DOM-elementen, moeten native properties zoals een this.src  this.value  this.checked enz, .prop is een zeer warm welkom in de familie. Voor anderen is het slechts een extra laag verwarring. Laten we dat duidelijk maken.

De eenvoudigste manier om het verschil tussen te zien .attr en .prop is het volgende voorbeeld:

<input blah="hello">
  1. $('input').attr('blah'): komt terug 'hello'zoals verwacht. Geen verrassingen hier.
  2. $('input').prop('blah'): komt terug undefined - omdat het probeert te doen [HTMLInputElement].blah - en er bestaat geen dergelijke eigenschap op dat DOM-object. Het bestaat alleen in de scope als een attribuut van dat element, d.w.z. [HTMLInputElement].getAttribute('blah')

Nu veranderen we een paar dingen zoals:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): komt terug 'apple' eh? Waarom niet "peren", omdat dit als laatste op dat element is ingesteld. Omdat de eigenschap is gewijzigd op het invoerattribuut, niet het DOM-invoerelement zelf - ze werken in principe bijna onafhankelijk van elkaar.
  2. $('input').prop('blah'): komt terug 'pear'

Het ding waar je echt voorzichtig mee moet zijn, is gewoon meng het gebruik van deze niet voor dezelfde eigenschap tijdens uw toepassing om de bovenstaande reden.

Zie een viool die het verschil demonstreert:  http://jsfiddle.net/garreh/uLQXc/


.attr vs .prop:

Ronde 1: stijl

<input style="font:arial;"/>
  • .attr('style') - retourneert inline stijlen voor het overeenkomende element, d.w.z. "font:arial;"
  • .prop('style') - geeft een stijlaangiftevoorwerp terug CSSStyleDeclaration

Ronde 2: waarde

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

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

* Opmerking: jQuery heeft om deze reden een .val() methode, die intern gelijkwaardig is aan .prop('value')


131
2018-05-19 10:18



TL; DR

Gebruik prop() over- attr() in de meeste gevallen.

EEN eigendom is de huidige status van het invoerelement. Een attribuut is de standaardwaarde.

Een eigenschap kan dingen van verschillende typen bevatten. Een kenmerk kan alleen strings bevatten


48
2017-07-16 09:45



Vuile controle

Dit concept is een voorbeeld waarbij het verschil waarneembaar is: http://www.w3.org/TR/html5/forms.html#concept-input-checked-dirty

Probeer het:

  • Klik op de knop. Beide selectievakjes zijn aangevinkt.
  • Schakel beide selectievakjes uit.
  • klik opnieuw op de knop. Alleen de prop selectievakje is aangevinkt. BANG!

$('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>

Voor sommige attributen zoals disabled op button, het toevoegen of verwijderen van het inhoudsattribuut disabled="disabled" schakelt altijd de eigenschap (genaamd IDL-attribuut in HTML5) in omdat http://www.w3.org/TR/html5/forms.html#attr-fe-disabled zegt:

Het uitgeschakelde IDL-kenmerk moet het uitgeschakelde content-kenmerk weerspiegelen.

dus je kunt ermee wegkomen, hoewel het lelijk is omdat het HTML zonder noodzaak aanpast.

Voor andere kenmerken zoals checked="checked" op input type="checkbox", dingen breken, omdat als je erop klikt, het vies wordt, en dan het toevoegen of verwijderen van checked="checked" inhoudsattribuut schakelt check niet meer uit.

Dit is waarom je het meest zou moeten gebruiken .propomdat het de effectieve eigenschap rechtstreeks beïnvloedt, in plaats van te vertrouwen op complexe bijwerkingen.


34
2017-07-06 11:43



Alles zit in het document:

Het verschil tussen kenmerken en eigenschappen kan belangrijk zijn in specifieke situaties. Vóór jQuery 1.6 hield de .attr () -methode soms rekening met eigenschapswaarden bij het ophalen van sommige kenmerken, wat tot inconsistent gedrag kon leiden. Vanaf jQuery 1.6 biedt de methode .prop () een manier om eigenschapwaarden expliciet op te halen, terwijl .attr () alleen kenmerken ophaalt.

Gebruik dus prop!


32
2018-05-03 19:35



attributen staan ​​in je HTML tekstdocument / bestand (== stel je voor dat dit het resultaat is van je html-markup die is geparseerd), terwijl
eigenschappenzijn in HTML DOM-boom (== in feite een actuele eigenschap van een object in JS-zin).

Belangrijk is dat veel van hen worden gesynchroniseerd (als u werkt class eigendom, class attribuut in html zal ook worden bijgewerkt; en anders). Maar sommige kenmerken kunnen worden gesynchroniseerd met onverwachte eigenschappen - bijvoorbeeld attribuut  checked komt overeen met eigendom  defaultChecked, zodat

  • het handmatig aanvinken van een selectievakje zal veranderen .prop('checked') waarde, maar zal niet veranderen .attr('checked') en .prop('defaultChecked') waarden
  • omgeving $('#input').prop('defaultChecked', true) zal ook veranderen .attr('checked'), maar dit zal niet zichtbaar zijn op een element.

Vuistregel is: .prop() methode moet worden gebruikt voor booleaanse attributen / eigenschappen en voor eigenschappen die niet bestaan ​​in html   (zoals window.location). Alle andere kenmerken (die u kunt zien in   de html) kan en zou moeten blijven worden gemanipuleerd met de .attr()   methode. (http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

En hier is een tabel die laat zien waar .prop() heeft de voorkeur (hoewel .attr() kan nog steeds worden gebruikt).

  table with preferred usage


Waarom zou u soms .prop () in plaats van .attr () willen gebruiken waar dit officieel is geadviseerd?

  1. .prop() kan elk type teruggeven - string, integer, boolean; terwijl .attr() geeft altijd een string terug.
  2. .prop() is naar verluidt ongeveer 2,5 keer sneller dan .attr().

26
2018-06-12 05:56



.attr():

  • Verkrijg de waarde van een attribuut voor het eerste element in de verzameling overeenkomende elementen.
  • Geeft de waarde van het element zoals het werd gedefinieerd in de HTML-code bij het laden van de pagina

.prop():

  • Verkrijg de waarde van a eigendom voor het eerste element in de verzameling overeenkomende elementen.
  • Geeft de bijgewerkte waarden van elementen die is gewijzigd via javascript / jQuery

18
2017-12-08 09:14



Meestal wil je eigenschappen gebruiken. Gebruik attributen alleen voor:

  1. Een aangepast HTML-kenmerk krijgen (omdat het niet is gesynchroniseerd met een DOM-eigenschap).
  2. Een HTML-kenmerk krijgen dat niet wordt gesynchroniseerd met een DOM-eigenschap, bijvoorbeeld verkrijg de "oorspronkelijke waarde" van een standaard HTML-kenmerk, zoals <input value="abc">.

13
2018-02-02 20:36