.prop() frente a .attr()
Entonces jQuery 1.6 tiene la nueva función prop()
.
$(selector).click(function(){
//instead of:
this.getAttribute('style');
//do i use:
$(this).prop('style');
//or:
$(this).attr('style');
})
o en este caso hacen lo mismo?
Y si tengo que cambiar a prop()
, ¿todas las llamadas antiguas attr()
se interrumpirán si cambio a 1.6?
ACTUALIZAR
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>
(ver también este violín: http://jsfiddle.net/maniator/JpUF2/ )
La consola registra getAttribute
como una cadena y attr
como una cadena, pero como prop
, CSSStyleDeclaration
¿por qué? ¿Y cómo afecta eso a mi codificación en el futuro?
Actualización 1 de noviembre de 2012
Mi respuesta original se aplica específicamente a jQuery 1.6. Mi consejo sigue siendo el mismo, pero jQuery 1.6.1 cambió ligeramente las cosas: frente a la pila prevista de sitios web rotos, el equipo de jQuery volvió attr()
a algo cercano (pero no exactamente igual) a su antiguo comportamiento para los atributos booleanos . John Resig también escribió en su blog sobre ello . Puedo ver la dificultad en la que se encontraban, pero todavía no estoy de acuerdo con su recomendación de preferir attr()
.
Respuesta original
Si alguna vez solo ha usado jQuery y no el DOM directamente, este podría ser un cambio confuso, aunque definitivamente es una mejora conceptual. Sin embargo, no es tan bueno para los millones de sitios que usan jQuery y que se romperán como resultado de este cambio.
Resumiré los principales problemas:
- Normalmente quieres
prop()
en lugar deattr()
. - En la mayoría de los casos,
prop()
hace lo queattr()
solía hacer. Reemplazar llamadas aattr()
conprop()
en su código generalmente funcionará. - Las propiedades son generalmente más sencillas de manejar que los atributos. El valor de un atributo solo puede ser una cadena, mientras que una propiedad puede ser de cualquier tipo. Por ejemplo, la
checked
propiedad es booleana, lastyle
propiedad es un objeto con propiedades individuales para cada estilo, lasize
propiedad es un número. - Cuando existen tanto una propiedad como un atributo con el mismo nombre, normalmente la actualización de uno actualizará el otro, pero este no es el caso para ciertos atributos de entradas, como y:
value
parachecked
estos atributos, la propiedad siempre representa el estado actual mientras que el El atributo (excepto en versiones antiguas de IE) corresponde al valor/verificación predeterminado de la entrada (reflejado en la propiedaddefaultValue
/defaultChecked
). - Este cambio elimina parte de la capa mágica de jQuery pegada delante de los atributos y propiedades, lo que significa que los desarrolladores de jQuery tendrán que aprender un poco sobre la diferencia entre propiedades y atributos. Ésto es una cosa buena.
Si eres un desarrollador de jQuery y estás confundido por todo este asunto de propiedades y atributos, debes dar un paso atrás y aprender un poco sobre ello, ya que jQuery ya no se esfuerza tanto por protegerte de estas cosas. Para las palabras autorizadas pero algo secas sobre el tema, están las especificaciones: DOM4 , HTML DOM , DOM Nivel 2 , DOM Nivel 3 . La documentación DOM de Mozilla es válida para la mayoría de los navegadores modernos y es más fácil de leer que las especificaciones, por lo que su referencia DOM puede resultarle útil. Hay una sección sobre propiedades de elementos .
Como ejemplo de cómo las propiedades son más sencillas de manejar que los atributos, considere una casilla de verificación que está inicialmente marcada. Aquí hay dos posibles piezas de HTML válido para hacer esto:
<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">
Entonces, ¿cómo puedo saber si la casilla de verificación está marcada con jQuery? Busque en Stack Overflow y normalmente encontrará las siguientes sugerencias:
if ( $("#cb").attr("checked") === true ) {...}
if ( $("#cb").attr("checked") == "checked" ) {...}
if ( $("#cb").is(":checked") ) {...}
En realidad, esto es lo más sencillo del mundo que se puede hacer con la checked
propiedad booleana, que ha existido y ha funcionado perfectamente en todos los principales navegadores con secuencias de comandos desde 1995:
if (document.getElementById("cb").checked) {...}
La propiedad también hace que marcar o desmarcar la casilla sea trivial:
document.getElementById("cb").checked = false
En jQuery 1.6, esto sin ambigüedades se convierte en
$("#cb").prop("checked", false)
La idea de utilizar el checked
atributo para escribir una casilla de verificación es inútil e innecesaria. La propiedad es lo que necesitas.
- No es obvio cuál es la forma correcta de marcar o desmarcar la casilla de verificación usando el
checked
atributo - El valor del atributo refleja el estado visible predeterminado en lugar del actual (excepto en algunas versiones anteriores de IE, lo que dificulta aún más las cosas). El atributo no le dice nada sobre si la casilla de verificación de la página está marcada. Consulte http://jsfiddle.net/VktA6/49/ .
Creo que Tim lo dijo bastante bien , pero retrocedamos:
Un elemento DOM es un objeto, una cosa en la memoria. Como la mayoría de los objetos en programación orientada a objetos, tiene propiedades . También, por separado, tiene un mapa de los atributos definidos en el elemento (generalmente provenientes del marcado que el navegador leyó para crear el elemento). Algunas de las propiedades del elemento obtienen sus valores iniciales de atributos con nombres iguales o similares ( value
obtiene su valor inicial del atributo "valor"; href
obtiene su valor inicial del atributo "href", pero no es exactamente el mismo valor; className
del atributo "clase"). Otras propiedades obtienen sus valores iniciales de otras maneras: por ejemplo, la parentNode
propiedad obtiene su valor en función de cuál es su elemento principal; un elemento siempre tiene una style
propiedad, tenga o no un atributo de "estilo".
Consideremos este ancla en una página en http://example.com/testing.html
:
<a href="foo.html" class="test one" name="fooAnchor" id="fooAnchor">Hi</a>
Algo de arte ASCII gratuito (y omitiendo muchas cosas):
+------------------------------------------------+ | ElementoAnclaHTML | +------------------------------------------------+ | href: "http://ejemplo.com/foo.html" | | nombre: "fooAnchor" | | identificación: "fooAnchor" | | className: "prueba uno" | | atributos: +-----------------------------+ | | | href: "foo.html" | | | | nombre: "fooAnchor" | | | | identificación: "fooAnchor" | | | | clase: "prueba uno" | | | +-----------------------------+ | +------------------------------------------------+
Tenga en cuenta que las propiedades y atributos son distintos.
Ahora bien, aunque son distintas, debido a que todo esto evolucionó en lugar de diseñarse desde cero, varias propiedades se escriben de nuevo al atributo del que derivaron si las configuras. Pero no todos lo hacen, y como puede ver href
arriba, el mapeo no siempre es una simple "transmisión del valor", a veces hay interpretación involucrada.
Cuando hablo de que las propiedades son propiedades de un objeto, no hablo en abstracto. Aquí hay algo de código que no es jQuery:
const link = document.getElementById("fooAnchor");
console.log(link.href); // Shows "http://example.com/foo.html"
console.log(link.getAttribute("href")); // Shows "foo.html"
El link
objeto es algo real y puede ver que existe una distinción real entre acceder a una propiedad y acceder a un atributo .
Como dijo Tim, la gran mayoría de las veces queremos trabajar con propiedades. En parte, eso se debe a que sus valores (incluso sus nombres) tienden a ser más consistentes en todos los navegadores. Generalmente solo queremos trabajar con atributos cuando no hay ninguna propiedad relacionada con ellos (atributos personalizados), o cuando sabemos que para ese atributo en particular, el atributo y la propiedad no son 1:1 (como con " href
href" arriba) .
Las propiedades estándar se establecen en las distintas especificaciones DOM:
- DOM2 HTML (en gran parte obsoleto, consulte la especificación HTML en su lugar)
- Núcleo DOM2 (obsoleto)
- Núcleo DOM3 (obsoleto)
- DOM4
Estas especificaciones tienen índices excelentes y recomiendo tener enlaces a ellas a mano; Los utilizo todo el tiempo.
Los atributos personalizados incluirían, por ejemplo, cualquier data-xyz
atributo que pueda poner en elementos para proporcionar metadatos a su código (ahora que eso es válido a partir de HTML5, siempre y cuando se ciña al data-
prefijo). (Las versiones recientes de jQuery te dan acceso a data-xyz
elementos a través de la data
función, pero esa función no es solo un acceso para data-xyz
atributos [hace más y menos que eso]; a menos que realmente necesites sus características, usaría la attr
función para interactuar con data-xyz
atributo.)
La attr
función solía tener una lógica complicada para obtener lo que pensaban que querías, en lugar de obtener literalmente el atributo. Combinaba los conceptos. Mudarse a prop
y attr
tenía como objetivo desconcertarlos. Brevemente, en la versión 1.6.0, jQuery fue demasiado lejos en ese sentido, pero rápidamente se volvió a agregar funcionalidad para attr
manejar las situaciones comunes en las que las personas usan attr
cuando técnicamente deberían usar prop
.
Este cambio ha tardado en llegar para jQuery. Durante años, se han contentado con una función attr()
cuyo nombre recuperaba principalmente propiedades DOM, no el resultado que se esperaría del nombre. La segregación de attr()
y prop()
debería ayudar a aliviar parte de la confusión entre los atributos HTML y las propiedades DOM. $.fn.prop()
toma la propiedad DOM especificada, mientras que $.fn.attr()
toma el atributo HTML especificado.
Para comprender completamente cómo funcionan, aquí hay una explicación ampliada sobre la diferencia entre los atributos HTML y las propiedades DOM:
Atributos HTML
Sintaxis:
<body onload="foo()">
Propósito: permite que el marcado tenga datos asociados para eventos, renderizado y otros fines.
Visualización: el atributo de clase se muestra aquí en el cuerpo. Es accesible a través del siguiente código:
var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");
Los atributos se devuelven en forma de cadena y pueden ser inconsistentes de un navegador a otro. Sin embargo, pueden ser vitales en algunas situaciones. Como se ejemplificó anteriormente, el modo Quirks de IE 8 (y siguientes) espera el nombre de una propiedad DOM en get/set/removeAttribute en lugar del nombre del atributo. Ésta es una de las muchas razones por las que es importante conocer la diferencia.
Propiedades DOM
Sintaxis:
document.body.onload = foo;
Propósito: Da acceso a propiedades que pertenecen a nodos de elementos. Estas propiedades son similares a los atributos, pero solo se puede acceder a ellas a través de JavaScript. Esta es una diferencia importante que ayuda a aclarar el papel de las propiedades DOM. Tenga en cuenta que los atributos son completamente diferentes de las propiedades , ya que esta asignación de controlador de eventos es inútil y no recibirá el evento (el cuerpo no tiene un evento de carga, solo un atributo de carga).
Visualización:
Aquí, verá una lista de propiedades en la pestaña "DOM" en Firebug. Estas son propiedades DOM. Inmediatamente notarás algunos de ellos, ya que los habrás utilizado antes sin saberlo. Sus valores son los que recibirás a través de JavaScript.
Documentación
- JavaScript: la guía definitiva de David Flanagan
- Atributos HTML, Centro de desarrollo de Mozilla
- Propiedades del elemento DOM, Centro de desarrollo de Mozilla
Ejemplo
HTML:<textarea id="test" value="foo"></textarea>
JavaScript:alert($('#test').attr('value'));
En versiones anteriores de jQuery, esto devolvía una cadena vacía. En 1.6, devuelve el valor adecuado, foo
.
Sin haber echado un vistazo al nuevo código para ninguna de las funciones, puedo decir con confianza que la confusión tiene más que ver con la diferencia entre los atributos HTML y las propiedades DOM que con el código en sí. Con suerte, esto te ha aclarado algunas cosas.
-Mate