En el enlace de datos de JavaScript, ¿por qué usar el atributo de datos en lugar de no solo extender los objetos DOM?

Contrariamente al pensamiento popular, los atributos data-* son una extensión de un objeto DOM. Simplemente es una extensión que forma parte de la especificación W3C (ver 3 Semántica, estructura y API de documentos HTML).

Una pequeña teoría …

Creo que el enlace de datos es actualmente un antipatrón recomendado. Viola el propósito original de HTML, que pretendía proporcionar estructura / relaciones de documentos / contenidos, no una gestión de datos operativa o dinámica (que es para lo que sirve JavaScript). Sin embargo; Como muestra la especificación, los atributos de datos existen claramente. Se supone que son para atributos ocultos (marcado), y no estaban destinados a ser controladores lógicos dinámicos. En otras palabras, los atributos de datos son un abuso de la intención del DOM. Muchos los consideran necesarios porque las implementaciones DOM de los navegadores simplemente no han evolucionado mucho y son complejas. Eso no significa que los enfoques de enlace de datos sean correctos / incorrectos, solo significa que el DOM es un desastre. Microsoft lanzó una mirada bastante entusiasta y profunda de por qué el DOM necesita cambiar: Modernizando el árbol DOM en Microsoft Edge.

Las operaciones informáticas más caras son los cambios DOM, en los que se basa el enlace de datos. La memoria existe con el propósito de almacenar y manipular datos que actualmente están siendo utilizados por un programa . Al almacenar datos en el DOM en lugar de la memoria, JavaScript debe monitorear el DOM (costoso) y responder a los cambios (es decir, manipular el DOM, también costoso). En algunos casos, los atributos de datos se “actualizan” para reflejar el mismo valor que tenían originalmente, lo que desencadena innecesariamente estos cambios. JavaScript es capaz de manejar todo esto en un medio diseñado para este propósito (memoria), por lo tanto, solo desencadena cambios DOM cuando es absolutamente necesario. Esta es la idea general detrás del DOM virtual.

Hacia el futuro …

Los elementos personalizados, que son 1 de 4 especificaciones de componentes web, webcomponents.org, ofrecen una forma emergente de ampliar y crear elementos DOM personalizados capaces de manejar datos “internamente” y responder a los cambios en consecuencia. Se supone que deben brindar a los desarrolladores una forma más intuitiva y efectiva de elegir el medio adecuado para las operaciones de presentación y datos. Sin embargo; la especificación está en modo borrador y el estado de implementación en los navegadores aún es un poco tosco, lo que dificulta la adopción. Es evidencia de un alejamiento del enlace de datos tal como lo conocemos actualmente, hacia un patrón que logra los mismos objetivos de una manera más efectiva.

Muchas respuestas pueden aplicarse a muchos contextos también. No los golpearé a todos, pero aquí hay un par de razones.

  1. No hagas esto. Los datos en los que se basa su aplicación nunca deben provenir del DOM (ya sea como objetos JS directamente o no). Es solo para representación visual. Mantenga sus datos en una tienda Javascript. Cualquier cosa con la que te sientas más cómodo. Redux, Backbone, infierno incluso GraphQL (que oscila por cierto).
  2. Legibilidad. No subestimes el valor que aporta tu código cuando es algo que otro desarrollador puede retomar justo donde lo dejaste. Su pregunta describe un escenario MUY improbable y la depuración de algo así en la producción sería una locura.
  3. Lógica. Aparte del hecho de que nadie hace esto (por lo tanto, su pregunta), requeriría más esfuerzo del que vale. Parece que quiere el máximo rendimiento porque estudió todas las comparaciones en http://jsperf.com y todo de Paul (Irish / Lewis). Incluso si este proyecto es por diversión y solo quieres aprender, no te beneficiará lo suficiente en rendimiento ni conocimiento / experiencia lo suficiente como para justificar el tiempo dedicado a la codificación y todo el tiempo dedicado a depurar o hacer cualquier otra cosa a partir de entonces.
  4. Esto debería ser el # 1: si esto produciría suficiente rendimiento para justificar los tres anteriores, hay / son problemas importantes en el resto de su proyecto que deben abordarse.

En el enlace de datos de JavaScript, ¿por qué usar el atributo de datos en lugar de no solo extender los objetos DOM?

Bueno, primero no puedes extender fácilmente los objetos DOM. El DOM los controla por una razón. Sin embargo, puede hacer algunas cosas realmente geniales dentro de una biblioteca, como usar un mapa débil. Si siempre tendrá una referencia al objeto dom cuando necesite sus valores, puede almacenarlos en un mapa débil con el objeto dom como clave. Entonces siempre puede recuperarlo del mapa, pero si el objeto se limpia, el mapa se limpia automáticamente.

El atributo de datos existe para el intercambio HTML / JS. En su HTML (que a menudo forma parte de una plantilla calculada del lado del servidor) puede incluir atributos data- * que se adjuntan al atributo de datos dom para que pueda leerlo fácilmente. Es una excelente manera de controlar las bibliotecas javascript que realizan mejoras progresivas sin tener que escribir ningún javascript usted mismo. En resumen, para muchas aplicaciones de línea de negocio, es exactamente la forma correcta de hacer las cosas.

Usted puede. D3 usó las propiedades de expansión la última vez que verifiqué, en .__ data__. Las propiedades de Expando estropearían la recolección de basura en IE hace mucho tiempo por razones que no recuerdo con precisión (creo que tenía que ver con referencias cíclicas entre DOM y JavaScript). Puede ser una forma conveniente de vincular un modelo a una vista, lo que imagino es por qué mbostock usó este enfoque. Hago esto con Web Components en mis Elementos personalizados (implementaciones nativas de v1) y parece útil. Creo que dataset / data- * atribuye todo el mapa a cadenas, por lo que sería de un valor más limitado y más trabajo para usar.

Promover:
Me estoy dando cuenta de que las personas no lo hacen hoy en día porque les han dicho que no lo hagan y creen que es un antipatrón. Si no puede trabajar con su equipo porque están tan atrapados en una convención, entonces eso realmente no va a funcionar, por lo que sería una buena razón para usar los atributos del conjunto de datos para asignar lo que desee.

Los componentes web, especialmente v1, ilustran un enfoque moderno (2017 y más allá) para usar enfoques nativos con cualquier propiedad, getter / setter, etc. que le guste:
Elementos personalizados v1: componentes web reutilizables | Fundamentos de la web
El | Desarrolladores de Google

Dadas las fuertes opiniones sin fundamento proporcionadas en las otras respuestas, sugiero que solo lea el manual anterior y use ambos conjuntos de datos / data- * junto con cualquier otro enfoque que desee para tener una mejor idea de cómo funcionan.

Personalmente, encuentro que adjuntar modelos directamente a los nodos DOM es útil en los casos en que el controlador necesita hacerlo con respecto a sus propias preocupaciones aisladas. Alternativamente, puede construir un sistema de mapeo más complejo (como se hace en jQuery y Angular 1 con $ scope) y luego debe mantener esa abstracción separada. Todos estos son enfoques correctos, tienen sus problemas con la limpieza, realmente depende de usted qué nivel de complejidad requiere su proyecto. Encuentro que las interfaces de usuario web son muy adecuadas para los enfoques de OOP basados ​​en eventos que usan patrones MVC donde cada componente (modelo o vista) puede adoptar un patrón sub MVC propio. (Básicamente, conviértase en modelos o vistas inteligentes con preocupaciones específicas por separado). Este es el caso que encontré en mi propio trabajo en el que adjuntar modelos directamente a elementos DOM es muy útil y también lo he visto en D3.