Recientemente, leí el artículo "Nuevas ideas para crear componentes de interfaz de usuario front-end" escrito por el tío Yu, que me recordó un artículo que compartí el año pasado , "Patrón de diseño JS para el desarrollo colaborativo con sentimientos" , que resonó un poco. .
Se dice que en la nueva versión del proyecto de cajero de Alipay el año pasado, probé este modelo de codificación de componentes por un tiempo. Aquí hay un poco de experiencia para compartir con ustedes:
Mirando hacia atrás en la clase abstracta mencionada anteriormente, los estudiantes que saben algo sobre patrones de diseño pueden encontrarla familiar. Sí, a primera vista parece una fábrica abstracta, pero combinada con las siguientes clases básicas, encontrará que no la anulé. getVessel, show, hide y otros métodos en cada clase básica, pero heredan directamente estos métodos en la clase abstracta. Definitivamente habrá personas que no entiendan por qué hacen esto. Es solo porque es JS, no JAVA. En mi opinión, un cierto grado de acoplamiento a cambio de suficiente flexibilidad no es excesivo, sin mencionar que esta clase abstracta debe garantizar una estabilidad absoluta y no se puede modificar a voluntad después de su formación.
A través de esta clase abstracta, asocio un objeto de contacto con un objeto contenedor e implemento la interacción más simple entre ellos a través del método de acción. "El más simple" no significa más que operaciones de mostrar u ocultar, así que definí los métodos de mostrar y ocultar. Obviamente, el comportamiento de interacción "más simple" no puede satisfacer el 100% del comportamiento del usuario, por lo que debo configurar un método setInterface y agregar clases de efectos a las clases que requieren efectos de interacción especiales. Finalmente, evite crear una instancia directa de esta clase abstracta cuando la use. Recuerde a todos en el método de acción que si desea crear una instancia de una operación, vaya a una clase de herencia específica para anular el método de acción.
A través de esta clase abstracta, podemos heredar los componentes más básicos de aPop, dropDown, xbox, xTab y otros... Estos ya se mencionaron en el artículo anterior. No entraré en detalles aquí. Cuando las clases básicas escritas aquí no pueden satisfacer las necesidades especiales, ¿cómo podemos desarrollar rápidamente componentes personalizados?
Tomemos xTab como ejemplo. Podemos usar este componente para completar el efecto de cambio básico entre puntos multitáctiles y múltiples contenedores, pero ¿qué pasa si necesitamos agregar algunos efectos de animación además de esto? Primero veamos el código de implementación de la pestaña de clase heredada:
Se puede encontrar que ejecuté el método setInterface después del método show. El método del mismo nombre en la clase abstracta se llamará de forma predeterminada. Este método de interfaz está diseñado para agregar clases de efectos interactivos adicionales para líneas interactivas similares. Por ejemplo: ahora queremos lidiar con el efecto de slideTab, entonces solo necesitamos heredar una clase de aplicación basada en xTab, anular el método setInterface y agregar una clase de animación para lograr el efecto de diapositiva, ¡y listo!
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:función(objetivo,buque){
this.parent(objetivo,buque);
this.anim(buque);
},
anim:función(vaso){
...
}
});
Para ser honesto, esta es una idea de diseño muy burda, pero nos permite pensar en el modo de codificación de componentes desde un ángulo diferente. Los anteriores son solo algunos intentos de aplicación superficiales, y la emoción continuará... ¡esperándote!
Reimpresión: http://ued.alipay.com/2010/06/proposed-front-end-ui-components-and-then-build-a-new-train-of-thinking/
AP.widget.xTab = AP.widget.basic.extend({
bindEvents:función(objetivo,buque){
E.on(objetivo,esta.opciones.tipo de evento,esta.acción,objetivo,esta);
E.on(ventana,'cargar',this.oXtab,objetivo,this);
},
acción:función(e,objetivo){
this.switchTab(e,objetivo);
},
switchTab:función(e,objetivo){
...
for(i=0,len=tabs.length;i<len;i++){
var hash = pestañas[i].href.split("#")[1];
var buque = D.get(hash + 'Extender');
si(buque){
this.hide(buque);
}
D.removeClass(tabs[i].parentNode,'actual');
if(destino.href == pestañas[i].href){
D.addClass(target.parentNode,'actual');
si(buque){
this.show(buque);
}
//Establecer varias interfaces de aplicación
this.setInterface(objetivo,buque);
}
E.preventDefault(e);
}
},
mostrarTab: función(índice){
...
},
//Inicializar pestaña de posicionamiento
oXtab:función(objetivo,e){
...
}
});
AP.widget.basic = nuevo AP.Class({
setOptions:función(opciones){
//Configuración de la interfaz
},
inicializar: función (objetivos, opciones) {
//Método de inicialización, el propósito es establecer la asociación entre los elementos del subconjunto de objetivos y un método
},
getVessel:función(objetivo){
//Obtener el contenedor que satisface la relación de mapeo de destino
},
bindEvents:función(objetivo,buque){
// Vincula aquí la acción desencadenante del objetivo
},
acción:función(){
// La función de ejecución activada por el evento vinculado al objetivo contiene la lógica que desea ejecutar.
},
mostrar:función(){
//mostrar contenedor
},
ocultar:función(){
//ocultar contenedor
},
establecerInterfaz:función(){
//Establece la interfaz compartida por cada componente
}
})