Este artículo es largo, pero realmente es contenido muy valioso y práctico. Expone algunas normas y recomendaciones sobre el uso de HTML, JavaScript, CSS y jQuery. Los desarrolladores frontend pueden leerlo con atención y compararlo con sus hábitos habituales para ver si hay algo que mejorar...


HTML

¿Qué pasa, DOCTYPE?

No definir el DOCTYPE es un crimen castigado con pena de muerte. Antes probablemente usabas el siguiente DOCTYPE, pero debes saber que ya existe un código más limpio y claro que lo ha reemplazado.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Lo ideal es usar el DOCTYPE de HTML5; todos los navegadores modernos lo soportan, e incluso los navegadores que no soportan HTML5, como IE6 e IE7, entrarán en modo estándar gracias a él. VerFuente。

<!DOCTYPE html>

Escribe marcado válido y semánticamente claro

Escribir el código de un sitio con HTML limpio y semánticamente claro es algo que siempre buscamos con empeño. A veces descubrimos que la forma en que otros configuraron la página nos limita, o a veces escribimos plantillas de correo en formato HTML. Pero nunca te desvíes de las especificaciones de HTML, ni siquiera para resolver un bug de compatibilidad con un navegador concreto.

Todos los títulos deberían empezar desde<h2>crearse por niveles, y los párrafos de texto siempre deben colocarse en<p>etiquetas, y así sucesivamente. Si escribes HTML con semántica clara, las páginas resultantes serán más ordenadas, concisas y fáciles de parsear por los rastreadores de los motores de búsqueda. Es la forma más sencilla de optimización SEO que puedes aplicar.

Mira el siguiente párrafo, ¿cuál crees que es más ordenado? ¿Este?

<span class="sectionHeading">A Heading</span>
<br /> <br />
Lorem ipsum dolor sit amet. ...
<br /> <br />

¿O este?

<h2>A Heading</h2>
<p>
    Lorem ipsum dolor sit amet. ...
</p>

Manejo del clic con el botón central del ratón

Una de las deficiencias de usabilidad más frustrantes en las aplicaciones web modernas es la variación de la funcionalidad de los hiperenlaces. Algunos elementos que parecen hiperenlaces pueden tener asignada una función de clic mediante JavaScript, lo que rompe la función del clic con el botón central (abrir la página del enlace en una nueva pestaña). Incluso si pueden abrirse en una pestaña nueva, solo tienen un#href que te llevará de vuelta a la misma página.

Un ejemplo moderno y popular que ilustra perfectamente este problema es Twitter. En toda su aplicación, hacer clic con el botón central en un nombre de usuario o avatar produce resultados completamente distintos.

<!-- 旧的方式,破坏网页语义 -->
<a href="../index.html"></a>

<!-- 如果鼠标点击不能产生一个页面,那就不是超链接 -->
<span class="link" role="link"></span>

Otra alternativa es usar#rutas guiadas, que mapean URLs normales a#enlaces guiados, y luego obtienen fragmentos de página mediante AJAX. Las bibliotecas que ofrecen esta funcionalidad deberían poder mostrar la página normalmente al hacer clic con el botón central, o cargar el contenido de la página en el área designada al hacer clic con el botón izquierdo. Sin embargo, hay que proceder con cautela, ya que muchos consideran quelos enlaces # están dañando las aplicaciones web.。

Representar información de contacto con Microformats

Microformat es una forma de facilitar que las máquinas lean la información de contacto. La clase hCard (no vCard) se usa para definir el tipo de contenido que contienen los elementos. Este contenido puede ser extraído y resaltado por los navegadores.

<span class="tel">
    <span class="type">home</span>:
    <span class="value">+1.415.555.1212</span>
</span>

Si alguna vez has navegado por una página web que utiliza este formato, notarás que programas como Skype pueden detectar fácilmente qué números de la página son números de teléfono. Safari en dispositivos iOS también puede hacer algo similar.

Para más información sobre Microformat, consultahttp://microformats.org/wiki/hcard

Las imágenes deben tener texto 'Alt'

<img>Las etiquetas necesitanalttexto, para verificar y cumplir con los requisitos de legibilidad. En elaltatributo, el texto debe poder describir el contenido que muestra la imagen o el efecto que se pretende lograr, a menos que la imagen no sea importante.

Si la imagen es solo una viñeta en una lista u otro icono irrelevante, es mejor dar alaltatributo una cadena vacía, pero sigue dejándolo. Así los lectores de pantalla lo ignorarán, en lugar de leer "viñeta" veinte veces seguidas.

<img src="dog.gif.html" alt="Fido and I at the park!" />
<!-- 很好,描述清晰 -->

<img src="bullet.gif.html" alt="bullet" />
<!-- 不好,显得多余 -->

<img src="bullet.gif.html" alt="" />
<!-- 好 -->

Usa la etiqueta table solo para datos tabulares

La etiqueta table siempre debe usarse solo para mostrar datos tabulares. La única excepción es al escribir correos en formato HTML, donde table puede ser la única opción de maquetación soportada por algunos clientes de correo problemáticos.

Por legibilidad, los encabezados de tabla siempre deben usar<th>elemento. También recuerda establecercellpadding, cellspacingyborderel valor de0, ya que estos estilos son más fáciles de mantener consistentes al controlarlos con CSS.

<table cellpadding="0" cellspacing="0" border="0">
    <thead>
        <tr>
            <th>
                Cell Header
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                Cell Item
            </td>
        </tr>
    </tbody>
</table>

Usa jQuery y los widgets de jQuery UI

jQuery y jQuery UI están hechos para ofrecer una apariencia y funcionalidad casi idénticas en los distintos navegadores. jQuery UI está diseñado para cumplir con WAI WCAG 2.0 y WAI ARIA, por lo que adoptar este framework evita todas las incertidumbres de los plugins o scripts que se ejecutan en tu sitio.


JavaScript

Espaciado y formato del código

Cualquier discusión sobre formato de código, espaciado y posición de las llaves genera un acalorado debate. Para esto, creo que la regla más simple es: a menos que estés dispuesto a reformatear todo el archivo de código, respeta y mantén el formato del archivo existente. Esto significa que si ves que en un archivo JS las llaves no se escriben en una línea nueva, tu código debe mantener las llaves en la misma línea. Si tu código no es consistente con el resto del archivo, no debería pasar el proceso de revisión de código.

Un formato de código consistente hace que el código sea más legible y también significa que es fácil de modificar con comandos de buscar/reemplazar. Afortunadamente, nuestros propios hábitos de programación son muy similares a las recomendaciones oficiales de jQuery. Hay pequeñas diferencias, pero son cuestiones personales o cosas que sentimos que no podíamos mantener. VerGuía de estilo del núcleo de jQuery

Espaciado entre caracteres

// 不好
if(blah==="foo"){
    foo("bar");
}

// 好 :)
if (blah === "foo") {
    foo("bar");
}

Llaves en la misma línea

// 不好
if (foo)
{
    bar();
}

// 好 :)
if (foo) {
    bar();
}

Usa siempre llaves

// 不好
if (foo)
    bar();

// 好 :)
if (foo) {
    bar();
}

Manejo de cadenas

Usa siempre comillas dobles para las cadenas. A algunas personas les encantan las cadenas de estilo C (comillas simples), pero este hábito conduce a conflictos de estilo dentro del script. El manejo de cadenas al estilo C exige que las cadenas vacías y los caracteres individuales se envuelvan en comillas simples, mientras que las frases y palabras deben envolverse en comillas dobles.

Comentarios

La necesidad de añadir comentarios al código a toda costa viene impulsada por gerentes, supervisores y otras personas que rara vez tocan el código. Esa necesidad no es más que una casilla de verificación en las métricas de evaluación de los empleados, y el tiempo invertido en ello casi no aporta nada. Si los desarrolladores receptivos siguieran las sugerencias presentadas en este documento, su código sería bastante fácil de leer y claro de un vistazo, tanto que describirlo con comentarios resultaría vergonzosamente redundante. Veamos el siguiente ejemplo. Aquí, las variables booleanas se plantean como preguntas y las funciones tienen nombres intuitivos.

if (user.hasPermission) {
    editPage();
}

Al menos en este escenario, los comentarios son completamente innecesarios.

Casos en los que los comentarios son importantes

En un proyecto, siempre hay partes difíciles de consultar y entender. Por ejemplo, una expresión regular compleja, o una función matemática que calcula ángulos o convierte entre grados y radianes. Sin comentarios como esos, un lector principiante o intermedio no tendrá ni idea del significado del script.

// 校验美国电话号码的正则表达式,号码格式是 (XXX) XXX-XXXX (减号、空格和括号都是可选的,可以有也可以没有)
var phoneRegEx = /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;

Usa siempre el operador ===

Usar el operador == puede hacer que errores frustrantes desaparezcan sin dejar rastro. Permite que enJavaScript GardenLa tipificación débil está claramente explicada en. Usar el operador estricto === no realiza coerción de tipos, permitiendo así evaluar estrictamente las diferencias entre dos objetos. Una vez más, para más detalles consulteJavaScript Garden。

var zeroAsAString = "0";

if (zeroAsAString == 0) {
    // 这样也能判断为true,呵呵...
}

if (zeroAsAString === 0) {
    // 判断为false
}

Excepción

Al comparar con null, se permite usar el operador ==, porque detecta tanto la propiedad null como undefined. Si no entiendes completamente este principio, sigo recomendando que uses el operador ===.

var foo = null;

// foo 是 null, 但 bar 是 undefined ,因为它尚未被声明
if (foo == null && bar == null) {
    // 上面的判断还是成立的
}

Al usar .parseInt(), especifica siempre el segundo parámetro 'radix'

Al parsear una cadena a un entero, un buen hábito es especificar el segundo parámetro de base — determina en qué base numérica se convertirá la cadena. Cuando la cadena comienza con0al inicio, de forma predeterminada se activa16base como radix. La mayoría de los usuarios principiantes e intermedios solo usarán10esta base. Gracias a João Moreno por registrar estaerrata。

alert( parseInt("08") ); // alerts: 2

alert( parseInt("08", 10) ); // alerts: 8

Evita comparar con true y false

Comparar directamente los valores de true y false no es necesario. A veces ser explícito puede ayudar, pero sigue siendo código extra.

if (foo === true) {
    // 用了 === 倒是不错,可这是多余的
}

if (foo) {
    // 赞!
}

if (!bar) {
    // 反过来也赞
}

Evita contaminar el espacio de nombres global

La dependencia excesiva de variables globales es algo de lo que todos en nuestro equipo — especialmente yo — nos sentimos particularmente culpables. La discusión sobre por qué las variables globales son malas es bastante directa: aumenta la probabilidad de conflictos entre scripts y variables, y los archivos fuente y el propio espacio de nombres se llenan de innumerables variables con nombres ambiguos.

Douglas CrockfordCreo firmemente que la calidad del código de una aplicación JavaScript puede evaluarse por la cantidad de variables globales que usa; cuanto menos, mejor. Como no todo puede definirse como local (aunque, siendo honestos, lo que estás considerando ahora sí puede, no seas perezoso), necesitas encontrar formas de organizar tus variables para evitar conflictos y minimizar la expansión del espacio de nombres. El método más simple es adoptar una variable única o reducir al máximo los módulos que usan esas variables globales. Crockford mencionó que YUI usa solo una variable global, YAHOO. En su artículo"Global Domination"analiza más detalles.

Considera este caso: en aplicaciones web pequeñas, las variables globales suelen usarse para guardar ajustes a nivel de aplicación. Puedes definir un objeto con el nombre de tu proyecto o settings, lo cual es mejor en general.

// 被污染的全局命名空间
var settingA = true;
var settingB = false;
var settingC = "test";

// 用 settings 作为对象命名
var settings = {
    settingA: true,
    settingB: false,
    settingC: "test"
}

Sin embargo, si podemos reducir la probabilidad de conflictos evitando variables globales, pero estandarizamos el espacio de nombres con el mismo nombre, ¿no aumentaría la probabilidad de conflictos entre aplicaciones? Bueno, esa preocupación es válida. Por eso, se recomienda usar el nombre específico de tu aplicación como espacio de nombres global, o reasignar tu espacio de nombres con el mismo patrón que usa jQuery.$.noConflict()método.

var myAppName = {
    settings: {
        settingA: true
    }
}

//访问全局变量
myAppName.settings.settingA; // true

Nombrado de variables en notación camelCase

El nombrado en camelCase para variables JavaScript es estándar en la mayoría de los entornos de programación. Un lector mencionó en los comentarios la única excepción: las constantes deben referenciarse con mayúsculas y guiones bajos.

var X_Position = obj.scrollLeft;

var xPosition = obj.scrollLeft; // 更好,更简洁

SCENE_GRAVITY = 1; // 常量

Rendimiento de bucles: almacenar en caché la longitud del array

Los bucles son probablemente la parte más importante del ajuste de rendimiento en JavaScript. Ahorrar uno o dos milisegundos dentro de un bucle puede suponer varios segundos en total. Un truco es almacenar en caché la longitud del array para no tener que calcularla en cada iteración.

var toLoop = new Array(1000);

for (var i = 0; i < toLoop.length; i++) {
    // 败家玩意 - 长度会反复算 1000 次你知道不?
}

for (var i = 0, len = toLoop.length; i < len; i++) {
    // 会过日子 - 长度只计算一次,然后缓存了
}

Excepción

Si recorres un array para buscar y eliminar un elemento, eso cambia la longitud del array. En cualquier momento en que añadas o elimines elementos dentro del bucle para cambiar la longitud del array, te estás buscando problemas. En ese caso, o restableces la longitud del array después de cada cambio, o no la almacenes en caché.

Rendimiento de bucles: usar 'break;' y 'continue;'

La capacidad de saltar iteraciones y de salir de los bucles es muy útil para evitar ciclos de bucle costosos.

Si estás buscando dentro de un bucle, ¿qué haces después de encontrar lo que buscas? Por ejemplo, en un bucle de 1000 elementos, llegas a la mitad y encuentras lo que querías. ¿Dejas que el bucle continúe iterando sobre los 500 elementos restantes, ignorando que las declaraciones if posteriores ya no tendrán oportunidad de cumplirse? ¡No! Deberías salir del bucle, ¡sin duda!

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (i === 500) {
        break;
    }
    console.log(i); // 这样只会输出 0 - 499
}

Otro problema es saltar una iteración específica y continuar con el bucle. Aunque condiciones como par/impar pueden manejarse reemplazandoi++pori + 2, algunas condiciones aún requieren una detección específica y luego activar una operación de salto. Cualquier cosa que evite ejecutar la iteración completa es útil.

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (condition) {
        continue;
    }
    doCostlyStuff();
}

No pases demasiados argumentos a las funciones

En cuanto a legibilidad, por no decir otra cosa, la siguiente forma es pésima:

function greet(name, language, age, gender, hairColour, eyeColour) {
    alert(name);
}

El siguiente ejemplo construye previamente un objeto como argumento, o pasa un objeto en línea, lo cual es mucho mejor.

function greet(user) {
    alert(user.name);
}

greet({
    name: "Bob",
    gender: "male"
});

Asigna 'this' a 'self'

Al escribir código JavaScript orientado a objetos (OO), debes comprenderthisel alcance de. Independientemente del patrón de diseño que uses para construir pseudo-clases, unathisreferencia a es la forma más simple de apuntar a una instancia. Cuando empieces a integrar los métodos auxiliares de jQuery con tus pseudo-clases, notarásthisel cambio en el alcance de.

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {
    // this = Bob
    $(this.friends).each(function() {
        // this = Bob.friends[i]
        if (this.name === toFind) {
            // this = Barry
            return this;
        }
    });
}

En el ejemplo anterior,thispasa de ser una referencia aBob, a convertirse en una referencia a su amigoBarry. Comprenderthisel cambio en el valor de con el tiempo es importante. Dentro de una función de prototipo,thisapunta a la instancia actual de la pseudo-clase en cuestión (aquíBob). Y una vez que entramos en el$.each()bucle,thisse reasigna alielemento del array que se está procesando.

La solución es reasignar el valor dethisaselfo_self. Aunqueself(sin guion bajo) no es unapalabra reservada, síes windowuna propiedad del objeto. Aunque el ejemplo que usé arribaselffue tomado del código fuente de jQuery, ellos también han reconocido este error y tienen la intención decorregir la situación actual, es decir, cambiar a_self. Personalmente, sigo prefiriendo usarself, por ninguna otra razón que su simplicidad — aunque puede provocar errores muy confusos. En resumen, usarselfes arriesgado; úsalo con precaución.

En el siguiente ejemplo, aprovecharé mejor los argumentos proporcionados en el$.each()helper, mientras reasigno el valor dethis.

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {

    // 就这一次用到了 "this"
    var _self = this;

    $(_self.friends).each(function(i,item) {
        if (item.name === toFind) {
            return item;
        }
    });

}

¿Puedo usar Boolean?

Las variables booleanas deben poder identificarse fácilmente por su nombre. Puedes usar prefijos comois, canohaspara formar una pregunta.

isEditing = true;

obj.canEdit = true;

user.hasPermission = true;  

Minimiza los repintados y los reflows

Los repintados y los reflows están relacionados con el proceso de volver a renderizar el DOM, que ocurre cuando se cambian propiedades o elementos específicos. Un repintado se activa cuando se altera la apariencia de un elemento sin ajustar el diseño.artículodescribe estos cambios como cambios de estilo, como la visibilidad o el color de fondo. El reflow es una operación más costosa, provocada por cambios que ajustan el diseño de la página. Por ejemplo, añadir o eliminar elementos, cambiar el ancho o el alto de un elemento, o incluso cambiar el tamaño de la ventana del navegador. El peor caso es un efecto dominó donde el reflow provoca que los elementos ancestros, hermanos e hijos también necesiten reflow.

Sin duda, los repintados y los reflows deberían evitarse en la medida de lo posible, pero ¿cómo lograrlo?

Ejemplo de reflow

En realidad, no es que el siguiente código sea malo. Pero supongamos primero que el arrayarrtiene 10 elementos

var myList = document.getElementById("myList");

for (var i = 0, len = arr.length; i < len; i++) {

    myList.innerHTML += "<li>" + arr[i].title + "</li>"; //重新布局 -- 增加到元素

}

En elforbucle anterior, cada iteración activa un reflow. 10 iteraciones significan 10 reflows.

Ahora considera el siguiente código:

var constructedHTML = "";

for (var i = 0, len = arr.length; i < len; i++) {
    constructedHTML += "<li>" + arr[i].title + "</li>"; //没有重新布局 - 增加到字符串
}

document.getElementById("myList").innerHTML = constructedHTML; //在这里重新布局

En este escenario, los elementos que se deben añadir se construyen en una cadena. No se produce ningún reflow dentro del bucle porque el DOM no cambia. Solo cuando el array se ha recorrido por completo y la cadena construida se aplica a cierta propiedad de un objeto,innerHTML, es cuando se produce el único reflow de la función.

Hay innumerables reflows y repintados que pueden evitarse; con suerte, conocerás esos trucos. Hay abundante material de lectura sobre este tema, pero la mayoría de él hace referencia al artículo de Nicole Sullivanartículo, que es un punto de partida perfecto. Además de las lecciones de aquí, hay otras lecciones importantes que aprender al tratar con los diversos términos técnicos de la era de la "web 3.0" y HTML5. El análisis anterior se aplica directamente a escribir código jQuery. Estos principios también son importantes al manipularcanvas, y además intenta mantener la tasa de fotogramas en el rango de 30-60.

No uses microsegundos para generar ID únicos

Desde los inicios del desarrollo web, ha sido popular un método para generar identificadores únicos. La práctica consiste en añadir el número de microsegundos desde el 1 de enero de 1970 a tu ID estático, como se muestra a continuación:

var myID = "static" + new Date().getTime();

Solía ser un método bastante infalible, porque incluso si dos fragmentos de código así se ejecutaran consecutivamente, habría unos pocos milisegundos entre ellos. Pero ahora los nuevos navegadores vienen con nuevos motores JavaScript, acompañados de velocidades de reloj cada vez mayores. A estas alturas, el código anterior tiene más probabilidades de producir el mismo valor de milisegundos que de producir una diferencia.

Esto puede provocar errores difíciles de depurar con los métodos tradicionales. Debido a que tu DOM se crea en tiempo de ejecución, las pruebas tradicionales sobre el código fuente de la página no pueden detectar el error de múltiples IDs duplicados. El mecanismo de manejo de errores de Javascript y jQuery toma la primera coincidencia como ID e ignora los demás IDs duplicados. ¡Así que ni siquiera lanza un error de JS!

Así no funciona; el único método real es poner puntos de interrupción y registros (logs) línea por línea. Pero si el punto de interrupción no está en el lugar correcto, ¡tus milisegundos no entrarán en conflicto!

La buena noticia es que hay muchos métodos alternativos para generar IDs únicos. Dicho de manera pedante, la función de números aleatorios de la computadora en realidad no es verdaderamente aleatoria, porque sigue derivando del tiempo del sistema. Aunque esto es digno de atención, la probabilidad de colisión de números aleatorios es minúscula.

var myID = "static" + Math.round(Math.random() * 10000);

Personalmente prefiero el método de generar un GUID manualmente. Técnicamente, un GUID se crea a partir de tu hardware, pero la siguiente función de Javascript lo hace bastante bien. Lo tomé prestado deuna publicación de stack overflowy es una función bastante útil.

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
   return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}

var myID = "static" + guid();

Detecta características, no tipos de navegador

¿El navegador del usuario soporta geolocalización? ¿Soporta web workers? ¿Video HTML5? ¿Audio HTML5? La respuesta solía ser así:

if ($.browser.msie) {
    // 哦,是IE啊,那肯定不支持
}

Pero el mundo cambia rápido. Las últimas versiones de IE casi pueden considerarse navegadores modernos, pero siguen causando dolor al desarrollo front-end. Las versiones anteriores de IE eran básicamente tan malas como sus predecesoras, lo que llevó a los programadores de Javascript perezosos a acostumbrarse a detectarif (ie)y luego ejecutar alguna sintaxis rota específica de Microsoft. Ahora IE9 ha abandonado esas funciones propietarias, y esas viejasif (ie)reliquias acaban siendo contraproducentes.

Entonces, ¿qué te parecería poder detectar cada característica sin tener que detectar el user-agent (que no es fiable y además se puede falsificar)?

Si tu respuesta es"eso es bastante fiable", entonces has acertado.

usarModernizrPues bien, esta es una biblioteca de Javascript en cuyo desarrollo participó el maestro de la industria Paul Irish. Esta biblioteca combina las tres grandes ventajas de amplia adopción, ligereza y una enorme cantidad dedocumentaciónLa implementación no requiere pensar, y es imprescindible para el hogar, los viajes y hasta para acallar bocas. Genera unModernizrobjeto que contiene los resultados de todas sus pruebas de detección, de modo que comprobar si una característica es compatible o no es tan simple como en el siguiente ejemplo:

// 检测浏览器是否支持canvas的老办法
if (!!document.createElement('canvas').getContext) { ... }

// 用 Modernizr 检测
if (Modernizr.canvas) { ... }

Usa milisegundos legibles

Una forma cómoda de escribir los milisegundos es hacerlos legibles. Es genial para principiantes, pero en la mayoría de los casos no es más que un truco.

// 这是3秒,30秒还是300秒啊?
var timeout = 30000;

// 增加了额外的计算开销,但是读和修改会更容易
var timeout = 30 * 1000;

Sobre el código jQuery

Encadena como un loco

Una de las mejores características de jQuery es el encadenamiento de funciones. Puede que ya hayas usado un poco, quizá encadenando llamadas simples una tras otra... Pero ¿alguna vez has recorrido el DOM saltando de un lado a otro como un perro rabioso? Mejor dedica tiempo a familiarizarte con.end()la función. Cuando empieces a saltar por el DOM desde el selector inicial, esta función será clave.

$(".quote")
    .hide()
    .find("a").text("Click here").bind("click",doStuff).end()
    .parent().removeClass().addClass("testimonial").draggable().end()
    .fadeIn("slow");

En el ejemplo anterior, cada vez que terminamos de operar sobre un objeto del DOM, y necesitamos recorrer el DOM en sentido inverso para volver al objeto original que referenciábamos, hay que usar.end()la función. Y entonces seguimos el rastro para volver a la posición original en el DOM.

Usa atributos data-*

Aquellos que llevan mucho tiempo escribiendo código Javascript (nativo, no jQuery) probablemente estén muy familiarizados con varios atributos. Intentan establecerlos, obtenerlos o abusar de ellos.relytitle ...

No digas que HTML5 o jQuery no han ayudado. La nueva especificación permite usar en elementos HTML eldata-prefijo para indicar atributos que contienen datos. jQuery convierte la cadena especificada en el tipo de dato Javascript correcto, y lo hace de maravilla. Vamos a crear un elemento con algunos atributos de datos.DIV 。

<div id="test" data-is-bool="true" data-some-number="123"></div>

Ahora, incluso si nuestros valores están envueltos en comillas, no se tratarán como cadenas:

typeof $("#test").data("isBool"); // boolean

typeof $("#test").data("someNumber"); // number

Mayúsculas y minúsculas especiales

Ten en cuenta que, para que estos fragmentos de código funcionen correctamente, la definición de atributos en el HTML debe usar letras minúsculas. Esto es importante. Sin embargo, si eres un desarrollador front-end muy competente, querrás usar notación camelCase para nombrar tus variables de datos. Como ocurre en muchas partes de Javascript, el guion inicial implica que la siguiente letra se aplicará a la mayúscula del camelCase. Pero usar camelCase en la definición de atributos HTML en el siguiente ejemplo esno es válidoy hará que el código Javascript anterior devuelvaundefined。

No funciona :(

<div id="test" data-isBool="true" data-someNumber="123"></div>

Sí funciona :)

<div id="test" data-is-bool="true" data-some-number="123"></div>

'.stop()' detiene la colaboración y la escucha

Vincular los efectos de animación de jQuery con los eventos de ratón es una parte clave de la interacción de usuario moderna en la web, pero incluso algunos de los sitios web más famosos lo hacen muy mal en este aspecto.Este artículoproporciona un ejemplo directo de implementación de animación y demuestra cuán discordantes se ven visualmente esas animaciones cuando se combinan. Por suerte, este problema se puede resolver fácilmente con un prefijo de función o en$.animatela llamada, añadiendo un parámetro, para resolverlo fácilmente.

Al usar$.animate, puedes añadir en los parámetrosqueue: falsepara evitar el encadenamiento. Atajos de animación como$.fadeIno$.slideDownestos no aceptanqueuela configuración; debes usar$.stopeste método para detener estas animaciones de antemano. En ciertos escenarios, se necesita que una animación se detenga directamente, o salte al estado final de la transformación. Te recomiendo que primero te familiarices con lo relacionado conclearQueueyjumpToEndestos dos parámetros y sudocumentación, porque, cielos, no tengo otra forma de ayudarte.

$("selector").stop(true,true).fadeOut();

$("selector").animate({
    property: value
}, {
    duration: 1000,
    queue: false
}

Optimiza tus selectores

jQuery es muy sofisticado. Puede hacer casi cualquier cosa, pero todavía no puede prepararte café; he oído que en la hoja de ruta de la versión 2.0 está previsto incluir esa característica. Una cosa que debes cuidar es no abusar de las capacidades de susizzleJSmotor de selectores. Para evitar este problema, hay dos estrategias:Cachear los resultados de los selectoresyusar selectores eficientes。

Cachear los resultados de los selectores

¿Cada vez que quieras modificar algo harás una consulta al DOM de alto costo, o guardarás una referencia de los elementos? La elección es obvia.

// before
$(".quote a").bind("click", doStuff); // DOM查询

// now
$(".quote a").addClass("quoteLink"); // DOM查询!!

// later
$(".quote a").fadeIn("slow"); // 又一次DOM查询!!!

Ignora el encadenamiento, así es mejor:

// before
var $quoteLinks = $(".quote a");  // 只需一次DOM查询
$quoteLinks.bind("click", doStuff);

// now
$quoteLinks.addClass("quoteLink");

// later
$quoteLinks.fadeIn("slow");

Usar selectores eficientes

Bien, jQuery/sizzleJS puede usar selectores CSS3 con facilidad, pero ¿cuál es el costo real? En este escenario, el navegador podría usardocument.querySelector(), pero también podría dividir tu cadena de selección y luego consultar el DOM manualmente.

// ID搜索是最快的查询方式,然后它获取孩子节点的列表,匹配其中class为'quotes'的元素
$("#quoteList").children(".quotes");

// 只在预先确定的bar元素下查找'foo'class
$(".foo",bar); 

Un bucle 'for' siempre es más rápido que el bucle 'each()'

No importa lo que ocurra en el desarrollo de navegadores en los próximos años, el buclefornativo siempre será más rápido que el bucle$.each()de jQuery. Cuando piensas en qué es realmente jQuery (una biblioteca que envuelve funciones nativas de JS), empiezas a darte cuenta de que el código Javascript nativo siempre será más rápido. Usar biblioteca o código nativo es un equilibrio entre velocidad de ejecución y velocidad de programación.

Es muy importante que, en funciones críticas de rendimiento que puedan llamarse cientos de veces por segundo, siempre usesforun bucle. Por ejemplo:

  • movimiento del ratón
  • intervalos de tiempo
  • bucles dentro de bucles

CSS

Entender el modelo de cajas es clave

El "modelo de caja" es un factor crítico y decisivo para entender cómo el navegador renderiza las páginas. Una comprensión completa de su complejidad puede simplificar tu trabajo de forma milagrosa. El modelo de caja describe la forma en que se calculan las dimensiones físicas de un elemento HTML. Si un elemento de bloque tiene un ancho fijo, digamos 100px, ¿cómo se deben determinar su padding, border y margin?

Muchos sitios web tienen descripciones en profundidad, pero seamos breves: en los navegadores que cumplen con los estándares, border y padding se colocan fuera del ancho especificado. Es mejor explicarlo con un gráfico. Por ejemplo, el siguiente código:

.foo {
    width: 150px;
    height: 150px;
    padding: 25px;
    border: 25px solid;
    margin: 20px;
}

Lo que quizá estimarías (modo Quirks)

padding y border se calculan hacia adentro, de modo que la altura y el ancho se mantienen en 150px.

Lo que ves (modo estándar)

Sin embargo, el ancho y la altura reales son 250px. Es decir, 150px + (2 * 25) + (2 * 25).

Si este resultado te parece extraño, no eres el único (bueno, eres un humano, solo que hay otros que piensan igual). Ahora hay una solución a mano: introducir una propiedad CSS llamadabox-sizing, esta propiedad es compatible conIE8 y versiones posterioresy se aplica a todos. Te permite elegir la forma exacta de calcular las dimensiones del elemento, lo que puede sacarte de apuros. Los parámetros específicos admitidos varían según el navegador y requieren prefijos de los fabricantes; para más detalles, consulta lacaniuse.com 。

/* 旧方法 (178 + 20 + 2 = 200) */
.foo {
    width: 178px;
    padding: 10px;
    border: 1px;
}

/* 更好的方法 */
.foo {
    width: 200px;
    padding: 10px;
    border: 1px;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
}

Aunque siempre puedes calcular mentalmente el ancho, restando y sumando entre los distintos píxeles (como se hacía en el primer método), cuando entran en juego diferentes unidades de ancho (como porcentajes o EM), ya nadie puede saber cómo hacerlo. Por ahora, aparte de envolver el elemento en un elemento padre, para asegurar que el ancho ypadding/margin/borderspuedan separarse por completo, no hay otra solución.

Saber cuándo usar float y cuándo usar position

La era de usar tablas para la maquetación ha terminado. Ahora debemos admitir que podemos concentrarnos en entender cómo funcionan float y position. Aquí se necesita dominar un modelo de pensamiento particular, y creo que lo mejor es aprenderlo mediante la práctica.

Usar float para extraer elementos del DOM y forzarlos a la izquierda o a la derecha es bastante fiable. Se han convertido en el comodín del desarrollo frontend en la era posterior al diseño con tablas, quizás porque antes los navegadores tenían undisplay: inlineyinline-blocksoporte deficiente, y los errores que surgían en el soporte de position.z-indexErrores. Pero ahora ya no hay excusa. inline-block está bien soportado, y con un pequeño ajuste se puede hacer funcionar en IE7.

Gracias a Dios, los antiguos debates que impedían el posicionamiento absoluto de elementos con CSS han desaparecido. En teoría, la propiedad de posicionamiento te permite colocar elementos en la página usando coordenadas X e Y, de una manera simple y directa que los desarrolladores de Flash deberían conocer bien.

Entender Position

Al posicionar elementos con CSS, es muy importante entender un hecho: la posición siempre es relativa al elemento padre más cercano que tenga una propiedad de posicionamiento. Cuando la gente empieza a usar CSS, hay un malentendido común de queposition: absolute;es relativa al elemento raíz de la página. Creo que este malentendido proviene de los casos en que el elemento no tiene ningún elemento padre con estilo position; en esos casos, su conclusión es correcta. Al recorrer el árbol DOM hacia arriba sin encontrar ningún elemento con estilo de posicionamiento, se posiciona respecto al elemento raíz de la página.

Entonces, siposition: absolute;saca al elemento del flujo en el que se encuentra, ¿cómo lo posicionas en relación con su elemento padre? El método es sencillo. El elemento padre necesita definirposition: relative;el estilo, y entonces todos los elementos hijos se colocan en el orden arriba, derecha, abajo, izquierda. Con este conocimiento, ¿cómo implementarías el siguiente diseño bastante intuitivo?

Usandofloat, necesitarás envolver estos elementos en un elemento padre, y luego.oneponer float a la izquierda, y luego ajustar.twoy.threedefloatymargin. Al final deberías escribir algo como lo siguiente:

.parent {
    /* ghetto clearfix */
    width: 310px;
    overflow: auto;
}
.one {
    width: 200px;
    height: 210px;
    float: left;
}
.two {
    width: 100px;
    height: 100px;
    float: right;
    margin-bottom: 10px;
}
.three {
    width: 100px;
    height: 100px;
    float: right;
}

Como dijimos antes, usarpositionnos permite mostrar elementos en la pantalla de forma muy explícita según coordenadas X e Y. El método con float anterior separa el texto largo de la página, mientras que el siguiente método asegura que todos los elementos estén en su posición normal, sin importar el contenido de la página.

.parent {
    position: relative;
    width: 310px;
    height: 210px;
}
.one, .two, .three {
    position: absolute;
}
.one {
    top: 0;
    left: 0;
    width: 200px;
    height: 210px;
}
.two {
    top: 0;
    right: 0;
    width: 100px;
    height: 100px;
}
.three {
    bottom: 0;
    right: 0;
    width: 100px;
    height: 100px;
}

Como se mencionó antes, hay algunosz-indexproblemas a considerar. Aunque el ejemplo anterior puede parecer un poco excesivo, una vez que empiezas a pensar en el posicionamiento, se abre un nuevo mundo de posibilidades.

Espacios en blanco

Si alternamos entre formatos de parámetros CSS de una sola línea y de varias líneas, el espacio en blanco en CSS también variará. No entraré en demasiado detalle sobre esto.

Espacio en blanco adecuado

/* 不好 */
.selector {display:none;background:#FF0000;color:#000000;}

/* 好 -- 单行 */
.selector { display: none; background: #FF0000; color: #000000; }

/* 好 -- 多行 */
.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

Las llaves no van en una línea nueva

.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

Indentación de los elementos hijos

Usarlo o no es cuestión de opinión; personalmente solo uso este formato en documentos CSS definidos en una sola línea.

.selector { display: none; background: #FF0000; color: #000000; }
    .selector a { text-decoration: none; }
    .selector span { font-weight: bold; }

Combinar e indentar las propiedades con prefijo de proveedor del navegador

.selector {
    background: #FFF; border: 1px solid #000; color: #EAEAEA;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
}

Formato abreviado de CSS

Agrupación de propiedades

Agrupar las propiedades es el método más efectivo para reducir en gran medida el tamaño de los archivos CSS. Es muy importante entender cómo se ordenan las propiedades (en el sentido de las agujas del reloj: arriba, derecha, abajo, izquierda) y cómo acortarlas aún más (arriba y abajo, izquierda y derecha).

/* 逐个定义,太长了 */
padding-top: 1px;
padding-right: 2px;
padding-bottom: 1px;
padding-left: 2px;

/* 上,右,下,左,好很多 */
padding: 1px 2px 1px 2px;

/* 上和下,左和右,最优 */
padding: 1px 2px;

De 0px a héroe

A una propiedad con valor0asignarle un tipo de unidad es redundante. No importa si un elemento está a0pxo a0 elephantsde la izquierda; lo que importa es que esté pegado a la izquierda.

/* 不好 */
padding: 0px 10px;

/* 好 */
padding: 0 10px;

Bloques de comentarios

Para la tarea de mantener múltiples secciones de estilos en una hoja de estilos, añadir comentarios a grandes bloques de CSS es una buena práctica. Obviamente, esto combina mejor con el estilo de una sola línea, aunque también es útil en el estilo de varias líneas. Usar guiones, signos igual o guiones bajos en los comentarios para enfatizar es cuestión de gustos; esta es la forma que me gusta:

/* === HORIZONTAL NAV === */
#horizNav { width: 100%; display: block; }
#horizNav li { display: block; float: left; position: relative; }
#horizNav li a { display: block; height: 30px; text-decoration: none; }
#horizNav li ul { display: none; position: absolute; top: 30; left: 0; }

/* === HOME PAGE - CAROUSEL === */
#carousel { width: 960px; height: 150px; position: relative; }
#carousel img { display: none; }
#carousel .buttons { position: absolute; right: 10px; bottom: 10px; }

Limpiar flotadores

Limpiar un<div>flotado solía implicar DOM adicional, porque conllevaba añadir un elemento de limpieza extra. Un método mejor es dar al elemento padre un ancho explícito ('auto' no funciona en todos los navegadores y escenarios) y establecer overflow en 'auto' u 'hidden'. 'hidden' tiene obviamente mejor compatibilidad, pero en algunas versiones compatibles con IE, 'auto' funciona mejor.

HTML:

<div class="parentElement">
    <div class="childElement">
        I'm floated left!
    </div>
    I'm normal text that wraps around the float
</div>

CSS:

.parentElement {
    width: 100%;
    overflow: hidden;
}
.childElement {
    float: left;
}

Un colaborador de este proyecto me alertó sobre el último clearfix.micro clear-fixSe considera lo bastante estable y compatible con los navegadores como para incluirlo en el último lanzamiento de HTML5 Boilerplate. Yorecomiendoencarecidamente que le eches un vistazo. Aunque no soy un gran fanático del CSS específico para navegadores ni de los:afterpseudo-elementos, este micro clearfix es realmente más robusto. También evita el problema de la contracción del margen superior.

Centrado vertical y horizontal

Centrar horizontalmente un elemento no es ciencia avanzada; estoy seguro de que la mayoría de vosotros conocéis el siguiente fragmento de código:

.class {
    width: 960px;
    margin: 0 auto;
}

Los desarrolladores frontend han utilizado este código durante mucho tiempo sin entender por qué no funciona para el centrado vertical. Desde mi punto de vista, es importante recordar que el elemento padre generalmente tiene unheight: auto;estilo, y tampoco tiene la altura del 100% necesaria para centrar verticalmente el elemento. Aplicarposition: absolute;transfiere efectivamente el elemento al modo de posicionamiento, y entonces el margen establecido en auto ayuda automáticamente a ajustar su posición, logrando el centrado.

.exactMiddle {
    width: 100px;
    height: 100px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}

Las desventajas de este método incluyen la falta de soporte en IE6 e IE7, y que cuando el navegador se reduce hasta ser más pequeño que el objeto centrado, no aparece la barra de desplazamiento. Enesta página webse enumeran más métodos (este es el cuarto), pero este es actualmente el mejor método.

Centrar verticalmente texto dentro de un elemento también es muy sencillo. Si el texto es de una sola línea, como en un elemento de navegación horizontal, puedes establecerline-heightla altura física del elemento.

#horizNav li {
    height: 32px;
    line-height: 32px;
}

Detecta características, no tipos de navegador

En la discusión anterior sobre la detección de características en Javascript, detectar que el navegador escualquier versiónde IE y luego aplicar ciertas propiedades se ha vuelto cada vez más problemático. El incansable Paul Irish lideró la ola del uso del método dedetección de versión de IEpara resolver estos problemas, peroModernizrnos ha salvado desde entonces. Modernizr, en el elemento raíz,<html>coloca unas clases que describen si ciertas características están soportadas. Luego, los estilos modernos pueden fácilmente generarse en cascada a partir de estas clases o eliminarse.

.my_elem {
   -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

/* 如果 box shadow 不支持, 就应用 borders 属性 */
.no-boxshadow .my_elem {
   border: 1px solid #666;
   border-bottom-width: 2px;
}

No abuses de !important

Depender de la!importantetiqueta es un fenómeno peligroso. Los casos en los que es imprescindible son contados y especiales. Suelen ser situaciones en las que necesitas sobrescribir otra hoja de estilos que no puedes editar o para la que no tienes permisos. Otro escenario es codificar rígidamente estilos en un elemento para evitar que los estilos generados en línea por Javascript tengan mayor prioridad. Pero la realidad es que!importanta menudo se utiliza como un atajo perezoso para hacer que un estilo prevalezca sobre otros, lo que causará muchos problemas en el futuro.

Sobre!importantLa mayoría de los usos de la etiqueta pueden evitarse si se entienden mejor las prioridades de los selectores CSS y cómo localizar elementos con mayor precisión. Cuanto más específico sea el selector, más probable es que sea aceptado como estilo aplicable. El siguiente ejemplo de vanseodesign muestra cómo funciona la especificidad.

p { font-size: 12px; }
p.bio { font-size: 14px; }

Sobre la prioridad de estilos,su artículoes mejor que cualquier cosa que yo pudiera escribir para explicar la herencia, así que por favor dale un voto positivo.

Compatibilidad descendente agresiva

Cabe señalar que este párrafo es mi opinión personal y solo se aplica a ciertos casos. En grandes proyectos comerciales o soluciones empresariales que dependen de navegadores antiguos, la postura de la compatibilidad descendente progresiva no será fácilmente aceptada.

Compatibilidad descendente progresiva significa que si un navegador concreto (de una versión antigua) no puede renderizar un efecto concreto, se debe ignorar directamente. Un botón CSS3 es un buen ejemplo. Efectos comoborder-radius, box-shadow, text-shadowygradientsse mostrarán en navegadores avanzados. Para navegadores un poco más antiguos, se puede usar una.PNGimagen como un recurso inofensivo, y la más elegante de todas las soluciones debería ser proporcionar un PNG-Fix para IE6, o usarfilterparámetros para reemplazar propiedades como gradients y shadows. Sin embargo, en este caso, el enfoque de compatibilidad descendente progresiva hará que ignores los navegadores antiguos y muestres en ellos un objeto plano y aceptable.

En pocas palabras, la compatibilidad descendente progresiva viene a ser:Si tu navegador no puede renderizar degradados o sombras de caja, es tu mala suerte.。

Aunque esto no es ideal para todas las situaciones, este método asegura que el proyecto se entregue a tiempo y que el producto principal sea utilizable, sin tener que depender de trucos para navegadores.


CSS3 y HTML5

Supongo que ya he hablado bastante sobre este tema. UsarModernizrpara detectar si características específicas de HTML5 y CSS3 están disponibles.

Uso y abuso de @font-face

Antes de considerar incrustar una fuente personalizada, es muy importante que revisesEULAy compruebes si se permite la incrustación web. Los proveedores de bibliotecas de fuentes, naturalmente, no quieren que los diseñadores y desarrolladores tengan la capacidad de alojar archivos de bibliotecas de fuentes directamente en su servidor, para que luego los usuarios avanzados puedan copiarlos. Algunos proveedores también prohíben incrustar tipos de archivo específicos, como.TTFy.OTF。

Si, tras una cuidadosa consideración, crees que la fuente deseada se puede incrustar, entonces echa un vistazo algenerador de @font-face. Utiliza laestructura a prueba de balas de @font-face de Fontspringy puede generar automáticamente todos los formatos de archivo necesarios.

Compatibilidad descendente

Afortunadamente, los navegadores ya manejan de forma elegante las características de HTML5 y CSS3 que no soportan. Añadido a<input />Los nuevos tipos de etiqueta, como "email", "search", etc., cuando no son soportados de forma nativa por el navegador, generalmente se degradan a normales<input type="text" />. De manera similar, las características CSS3 no compatibles simplemente no aparecen, y los diseños responsivos controlados por consultas de medios de altura y anchura no se aplican.

Los efectos CSS3 sofisticados deben aplicarse como una recompensa para los usuarios que utilizan navegadores modernos.

En la siguiente sección de "Recursos" se incluyen algunas bibliotecas que ayudan a que las funciones de HTML5 y CSS3 funcionen correctamente en una serie de navegadores antiguos.


Recursos

Los siguientes recursos son importantes para la estandarización del código y la interactividad de las páginas web modernas. Garantizan que las características de CSS3 y HTML5 puedan utilizarse en una serie de navegadores que anteriormente carecían de soporte.

  • jQuery Bibliotecas auxiliares de JavaScript
  • jQuery UI Hacen por la interacción/interfaz de usuario lo mismo que jQuery hace por JavaScript.
  • Modernizr ¡Detecta características, no detectes navegadores!
  • RespondJS Lleva el diseño responsivo a navegadores antiguos
  • @font-face Generator Incrustación completa de fuentes
  • RaphaelJS Gráficos vectoriales fáciles de usar y compatibles con todos los navegadores
  • HTML5 Boilerplate Es un buen punto de partida para cualquier proyecto. Sin embargo, incluso su versión "ligera" sigue siendo un poco pesada.
  • Twitter Bootstrap Te permite crear rápidamente prototipos y estilos para aplicaciones web sencillas.

Este artículo fue escrito por Tait Brown (@taitems), y esta versión en chino fue traducida porcoderLMNTraducción.