Con tanta gente que desarrolla complementos de jQuery, no es raro encontrar uno que sea simple, por falta de mejores palabras, apesta. No hay ejemplos ni documentación, el complemento no sigue las mejores prácticas, etc. Pero usted es uno de los afortunados: este artículo detallará las dificultades que debe evitar..
jQuery no es un extraño para aquellos de ustedes que frecuentan Nettuts +. Los increíbles jQuery de 30 días para aprender de Jeffrey Way (y varios otros tutoriales aquí y en otros lugares) nos han llevado a todos por el camino hacia el awesomesauce potenciado por Sizzle. En toda la exageración (y muchos saltos en la adopción de JavaScript por parte de los desarrolladores y proveedores de navegadores), muchos complementos han llegado a la escena. ¡Esto es en parte por qué jQuery se ha convertido en la biblioteca de JavaScript más popular disponible! El único problema es que muchos de ellos no son demasiado grandes..
En este artículo, nos centraremos menos en el JavaScript específicamente, y más en las mejores prácticas para la entrega de complementos.
Hay algunos patrones que son, más o menos, aceptados universalmente como "La forma correcta" para crear complementos de jQuery. Si no estás siguiendo estas convenciones, tu complemento puede ... ¡apestar! Considere uno de los patrones más comunes:
(función ($, ventana, indefinido) $ .fn.myPlugin = función (opts) var defaults = // configuración de sus valores predeterminados para las opciones // extender las opciones de los valores predeterminados con las opciones del usuario var options = $ .extend (por defecto, opta || ); devuelva this.each (function () // jQuery chainability // hacer cosas de plugin);) (jQuery, window);
Primero, estamos creando una función anónima que invoca a sí misma para protegernos del uso de variables globales. Pasamos en PS
, ventana
, y indefinido
. Los argumentos con los que se invoca la función de invocación propia son are jQuery
y ventana
; no se pasa nada para undefined, por lo que si decidimos usar la palabra clave undefined dentro del complemento, "undefined" en realidad será undefined.
Estos escudos de otros scripts asignan potencialmente un valor malicioso a
indefinido
, comocierto
!
PS
se pasa como jQuery; Lo hacemos de esta manera para asegurarnos de que, fuera de la función anónima., PS
Todavía puede referirse a algo completamente distinto, como Prototype.
Pasando la variable por la globalmente accesible. ventana
El objeto permite un código más comprimido a través de los procesos de minificación (lo que también debería estar haciendo).
A continuación, estamos utilizando el patrón de plugin jQuery, $ .fn.PluginName
. Esta es una forma de registrar su complemento para ser utilizado con el $ (selector) .method ()
formato. Simplemente extiende el prototipo de jQuery con su nuevo método. Si desea crear un complemento que defina una función en el objeto jQuery, agréguelo directamente, así:
$ .PluginName = function (options) // extender opciones, hacer cosas de plugin
Este tipo de plugin no será chainable, ya que las funciones que se definen como propiedades del objeto jQuery normalmente no devuelven el objeto jQuery. Por ejemplo, considere el siguiente código:
$ .splitInHalf = function (stringToSplit) var length = stringToSplit.length; var stringArray = stringToSplit.split (stringToSplit [Math.floor (length / 2)]); return stringArray;
Aquí, estamos devolviendo una serie de cadenas. Tiene sentido simplemente devolver esto como una matriz, ya que esto es probablemente lo que los usuarios querrán usar (y pueden envolverlo fácilmente en el objeto jQuery si lo desean). En contraste, considere el siguiente ejemplo artificial:
$ .getOddEls = function (jQcollection) // return jQcollection.filter (function (index) var i = index + 1; return (index% 2! = 0););
En este caso, el usuario probablemente espera que el objeto jQuery regrese de $ .getOddEls
; Por lo tanto, devolvemos el método de filtro, que devuelve la colección jQuery definida por la función que se pasa. Una buena regla general es envolver los elementos devueltos en la función jQuery, especialmente si se pueden encadenar; Si está devolviendo matrices, cadenas, números, funciones u otros tipos de datos, déjelos sin envolver..
Podría decirse que lo más importante que puede hacer cuando publica su código es agregar la documentación necesaria. La brecha entre lo que explicas a los desarrolladores y lo que el código realmente hace o puede hacer es el tiempo que los usuarios no quieren perder al descubrir los entresijos de tu código..
La documentación es una práctica que no tiene reglas rígidas; sin embargo, generalmente se acepta que cuanta más documentación (bien organizada) tenga, mejor.
Este proceso debe ser tanto una práctica interna (dentro de / intercalada a lo largo de su código) como una práctica externa (explicando cada método público, opción y múltiples casos de uso en una wiki o readme).
Los complementos más populares ofrecen acceso completo a las variables (lo que la mayoría de los complementos denominan objetos de "opciones") que un usuario puede querer controlar. También pueden ofrecer muchas configuraciones diferentes del complemento para que sea reutilizable en muchos contextos diferentes. Por ejemplo, consideremos un simple complemento deslizante. Las opciones que el usuario podría desear controlar incluyen la velocidad, el tipo y el retraso de la animación.
Es una buena práctica también otorgar al usuario acceso a los nombres de clase / ID que se agregan a los elementos DOM insertados o manipulados por el complemento. Pero más allá de esto, también pueden querer tener acceso a una función de devolución de llamada cada vez que la diapositiva hace la transición, o quizás cuando la diapositiva vuelve al principio (un "ciclo" completo).
Es su trabajo pensar en todos los usos y necesidades posibles del complemento..
Consideremos otro ejemplo: un complemento que realiza una llamada a una API debería proporcionar acceso al objeto devuelto de la API. Tomemos el siguiente ejemplo de un simple concepto de plugin:.
$ .fn.getFlickr = function (opts) return this.each (function () // jQuery chainability var defaults = // configurando sus opciones predeterminadas cb: function (data) , flickrUrl: // algún valor predeterminado para una llamada a la API // extender las opciones de los valores predeterminados con las opciones del usuario var options = $ .extend (predeterminado, opts || ); // llamar a la función asíncrona y luego llamar a la devolución de llamada // pasando el objeto api que se devolvió $ .ajax (flickrUrl, function (dataReturned) options.cb.call (this, dataReturned);););
Esto nos permite hacer algo en la línea de:
$ (selector) .getFlickr (function (fdata) // los datos de flickr están en el objeto fdata);
Otra forma de publicarlo es ofrecer "ganchos" como opciones. A partir de jQuery 1.7.1 y superiores, podemos usar .on (eventName, function () )
después de nuestra llamada de plugin para separar los comportamientos en sus propias funciones. Por ejemplo, con el complemento anterior, podríamos cambiar el código para que se vea así:
$ .fn.getFlickr = function (opts) return this.each (function (i, el) var $ this = el; var defaults = // configurando sus opciones predeterminadas flickrUrl: "http://someurl.com" // algún valor predeterminado para una llamada a la API var options = $ .extend (por defecto, opts || ); // llama a la función asíncrona y luego llama a la devolución de llamada // pasando el objeto api que se devolvió $ .ajax (flickrUrl, function (dataReturned) // hacer algunas cosas $ this.trigger ("callback", dataReturned);). error (function () $ this.trigger ("error", dataReturned;;)); );
Esto nos permite llamar al getFlickr
plugin y otros controladores de comportamiento de la cadena.
$ (selector) .getFlickr (opts) .on ("callback", function (data) // do stuff). on ("error", function () // maneja un error);
Puedes ver que ofrecer este tipo de flexibilidad es absolutamente importante; Mientras más complejas sean las acciones que tengan tus complementos, más complejo será el control que debería estar disponible..
Bien, la sugerencia número tres sugirió que entre las acciones más complejas que tienen tus complementos, más complejo debe ser el control. disponible. Sin embargo, un gran error es hacer demasiadas opciones para la funcionalidad del complemento. Por ejemplo, es ideal que los complementos basados en UI tengan un comportamiento predeterminado sin argumentos.
$ (selector) .myPlugin ();
Ciertamente, a veces esto no es realista (ya que los usuarios pueden obtener un feed específico, por ejemplo). En este caso, debes hacer un poco de trabajo pesado para ellos. Tener múltiples formas de pasar opciones al plugin. Por ejemplo, digamos que tenemos un sencillo complemento de recuperación de tweets. Debería haber un comportamiento predeterminado de ese programa de recuperación de tweets con una única opción requerida (el nombre de usuario que desea recuperar).
$ (selector) .fetchTweets ("jcutrell");
El valor predeterminado puede, por ejemplo, capturar un solo tweet, envolverlo en una etiqueta de párrafo y rellenar el elemento selector con ese html. Este es el tipo de comportamiento que la mayoría de los desarrolladores esperan y aprecian. Las opciones granulares deben ser solo eso: opciones.
Es inevitable, dependiendo del tipo de complemento, por supuesto, que tendrá que incluir un archivo CSS si está altamente basado en las manipulaciones de la interfaz de usuario. Esta es una solución aceptable al problema, en términos generales; la mayoría de los complementos vienen con imágenes y CSS. Pero no se olvide de la punta número dos: la documentación también debe incluir cómo usar / hacer referencia a las hojas de estilo e imágenes. Los desarrolladores no querrán perder tiempo buscando en su código fuente para resolver estas cosas.
Las cosas deberían ... trabajar.
Dicho esto, definitivamente es una buena práctica utilizar estilos inyectados (que son altamente accesibles a través de opciones de plugin) o estilos basados en clase / ID. Estas identificaciones y clases también deben ser accesibles, a través de las opciones mencionadas anteriormente. Sin embargo, los estilos en línea anulan las reglas CSS externas; se desaconseja la mezcla de los dos, ya que un desarrollador puede tardar mucho tiempo en descubrir por qué los elementos creados por su complemento no están respetando sus reglas de CSS. Usa tu mejor juicio en estos casos..
Como regla general, el CSS en línea es malo, a menos que sea tan mínimo que no garantice su propia hoja de estilo externa.
La prueba está en el pudín: si no puede proporcionar un ejemplo práctico de lo que hace su complemento con el código que lo acompaña, la gente se apagará rápidamente para usar su complemento. Simple como eso. No seas perezoso.
Una buena plantilla para ejemplos:
jQuery, como cualquier buena biblioteca de códigos, crece con cada lanzamiento. La mayoría de los métodos se mantienen incluso después de que el soporte esté en desuso. Sin embargo, se agregan nuevos métodos; Un ejemplo perfecto de esto es el .en()
Método, que es la nueva solución todo en uno de jQuery para la delegación de eventos. Si escribes un plugin que usa .en()
, La gente que use jQuery 1.6 o anterior estará fuera de suerte. Ahora no estoy sugiriendo que codifique el mínimo común denominador, pero, en su documentación, asegúrese de explicar qué versión de jQuery admite su complemento. Si introduce un complemento con soporte para jQuery 1.7, debería considerar mantener el soporte para 1.7 incluso una vez que se publique 1.8. También debe considerar aprovechar las características nuevas / mejores / más rápidas en jQuery a medida que salen.
¡Aliente a los desarrolladores a actualizar, pero no rompa su complemento con demasiada frecuencia! Una opción es ofrecer versiones "heredadas", no admitidas, de su complemento..
Es hora de morder la bala si aún no ha aprendido a usar el control de versiones..
Además de mantener la compatibilidad / compatibilidad con la versión de jQuery como parte de su documentación, también debe trabajar en el control de versiones. El control de versiones (específicamente, a través de GitHub) es en gran parte el hogar de la codificación social. Si está desarrollando un complemento para jQuery que desea publicar en el repositorio oficial, debe almacenarlo en un repositorio de GitHub de todos modos; es hora de morder la bala si no ha aprendido a usar el control de versiones. Hay innumerables beneficios para el control de versiones, todos los cuales están fuera del alcance de este artículo. Pero uno de los beneficios principales es que permite a las personas ver los cambios, las mejoras y las correcciones de compatibilidad que realiza, y cuando las realiza. Esto también abre el piso para la contribución y la personalización / extensión de los complementos que escribe..
El mundo no necesita otro plugin deslizante..
Ok, lo hemos ignorado durante bastante tiempo aquí: algunos "complementos" son inútiles o demasiado superficiales para justificar que se los llame complementos. ¡El mundo no necesita otro plugin deslizante! Cabe señalar, sin embargo, que los equipos internos pueden desarrollar sus propios complementos para sus propios usos, lo que está perfectamente bien. Sin embargo, si desea insertar su complemento en la esfera de codificación social, encuentre una razón para escribir más código. Como dice el dicho, no hay razón para reinventar la rueda. En su lugar, toma la rueda de alguien más y construye un auto de carreras. Por supuesto, a veces hay nuevas y mejores formas de hacer las mismas cosas que ya se han hecho. Por ejemplo, es muy posible que escriba un nuevo complemento de control deslizante si utiliza una tecnología más rápida o nueva..
Este es bastante simple: ofrece una versión reducida de tu código. Esto lo hace más pequeño y más rápido. También asegura que su Javascript está libre de errores cuando se compila. Cuando minimice su código, no olvide ofrecer también la versión sin comprimir, para que sus compañeros puedan revisar el código subyacente. Existen herramientas gratuitas y baratas para desarrolladores front-end de todos los niveles de experiencia.
Consulte la punta número trece para obtener una solución automatizada..
Cuando escribes un plugin, está destinado a ser usado por otros, ¿verdad? Por esta razón, el código fuente más efectivo es altamente legible. Si está escribiendo innumerables funciones inteligentes de estilo lambda de una línea, o si los nombres de sus variables no son semánticos, será difícil depurar errores cuando ocurran inevitablemente. En lugar de escribir nombres de variables cortos para ahorrar espacio, siga los consejos del consejo número nueve (¡redúzcalo!) Esta es otra parte de la buena documentación; Los desarrolladores decentes deberían poder revisar su código y entender lo que hace sin tener que gastar demasiada energía.
Si te encuentras llamando variables "
una
"o"X
", lo estás haciendo mal.
Además, si se encuentra consultando documentación para recordar qué tu propio El código de aspecto extraño lo está haciendo, es probable que también tenga que ser menos conciso y más explicativo. Restrinja el número de líneas en cada función a la menor cantidad posible; si se extienden por treinta o más líneas, podría haber un olor a código.
Por mucho que a todos nos guste usar jQuery, es importante entender que se trata de una biblioteca, y eso conlleva un pequeño costo. En general, no necesita preocuparse demasiado por cosas como el rendimiento del selector jQuery. No seas odioso, y estarás bien. jQuery está altamente optimizado. Dicho esto, si la única razón por la que necesita jQuery (o un complemento) es realizar algunas consultas en el DOM, puede considerar eliminar la abstracción por completo y, en cambio, seguir con el JavaScript de vainilla o Zepto.
Nota: Si decide quedarse con JavaScript de vainilla, asegúrese de estar usando métodos que sean de navegador cruzado. Es posible que necesites un pequeño polyfill para las API más nuevas..
Utilice Grunt. Período.
Grunt es una "herramienta de construcción de línea de comandos basada en tareas para proyectos de JavaScript", que se trató en detalle recientemente aquí en Nettuts +. Te permite hacer cosas como esta:
inicio ronco: jQuery
Esta línea (ejecutada en la línea de comandos) le indicará un conjunto de preguntas, como el título, la descripción, la versión, el repositorio de git, las licencias, etc. Estas piezas de información ayudan a automatizar el proceso de configuración de su documentación, licencias, etc..
Grunt hace mucho más que simplemente hacer un código personalizado para ti; también ofrece herramientas integradas, como la guía de códigos JSHint, y puede automatizar las pruebas QUnit para usted siempre y cuando tenga instalado PhantomJS (que Grunt cuida). De esta manera, puede optimizar su flujo de trabajo, ya que las pruebas se ejecutan instantáneamente en el terminal al guardar.
Oh, por cierto - tu hacer prueba tu código, ¿verdad? Si no es así, ¿cómo puede garantizar / declarar que su código funciona como se esperaba? Las pruebas manuales tienen su lugar, pero, si te encuentras refrescando el navegador innumerables veces cada hora, lo estás haciendo mal. Considere el uso de herramientas, como QUnit, Jasmine o incluso Mocha..
Las pruebas son particularmente útiles cuando se combinan las solicitudes de extracción en GitHub. Puede solicitar que todas las solicitudes proporcionen pruebas para garantizar que el código nuevo / modificado no rompa su complemento existente.
Si el concepto de probar los complementos de jQuery es nuevo para usted, considere la posibilidad de ver nuestro complemento de pantalla exclusivo Premium, Técnicas para probar los complementos de jQuery. Además, estamos lanzando un nuevo curso "Prueba de JavaScript con Jasmine" más adelante esta semana en el sitio!
No te haríamos ningún favor simplemente diciéndote lo que estás haciendo mal. Aquí hay algunos enlaces que te ayudarán a volver al camino correcto.!
Si está escribiendo un plugin de jQuery, es vital que se aleje de las dificultades enumeradas anteriormente. ¿Perdí alguna señal clave de un plugin mal ejecutado??