Récemment, j'ai lu l'article "Nouvelles idées pour créer des composants d'interface utilisateur front-end" écrit par Oncle Yu, qui m'a rappelé un article que j'ai partagé l'année dernière , "Modèle de conception JS pour le développement collaboratif avec sentiments" , qui a un peu résonné. .
On dit que dans la nouvelle version du projet de caisse d'Alipay l'année dernière, j'ai essayé ce modèle de codage de composants pendant un moment. Voici un petit bout d'expérience à partager avec vous :
En repensant au cours abstrait mentionné précédemment, les étudiants qui connaissent quelque chose sur les modèles de conception peuvent le trouver familier. Oui, à première vue, cela ressemble à une usine abstraite, mais combiné avec les cours de base suivants, vous constaterez que je n'ai pas outrepassé. getVessel, show, hide et d'autres méthodes dans chaque classe de base, mais a directement hérité de ces méthodes dans la classe abstraite. Il y aura certainement des gens qui ne comprendront pas pourquoi ils font ça. C'est simplement parce que c'est du JS, pas du JAVA. Un certain degré de couplage en échange d'une flexibilité suffisante n'est pas excessif à mon avis, sans compter que cette classe abstraite doit assurer une stabilité absolue. Il faut qu'elle ne puisse pas être modifiée à volonté après sa formation.
Grâce à cette classe abstraite, j'associe un objet contact à un objet conteneur et implémente l'interaction la plus simple entre eux via la méthode d'action. "Le plus simple" ne signifie rien de plus que des opérations d'affichage ou de masquage, j'ai donc défini les méthodes d'affichage et de masquage. Évidemment, le comportement d'interaction "le plus simple" ne peut pas satisfaire 100 % du comportement de l'utilisateur, je dois donc définir une méthode setInterface et ajouter des classes d'effets aux classes qui nécessitent des effets d'interaction spéciaux. Enfin, évitez d'instancier directement cette classe abstraite lorsque vous l'utilisez. Rappelez à tous les utilisateurs de la méthode d'action que si vous souhaitez instancier une opération, veuillez vous rendre dans une classe d'héritage spécifique pour remplacer la méthode d'action.
Grâce à cette classe abstraite, nous pouvons hériter des composants les plus basiques aPop, dropDown, xbox, xTab et autres... Ceux-ci ont déjà été mentionnés dans l'article précédent. Je n'entrerai pas dans les détails ici, je me concentrerai sur leur explication. lorsque les cours de base écrits ici ne peuvent pas répondre aux besoins particuliers, comment pouvons-nous développer rapidement des composants personnalisés.
Prenons xTab comme exemple. Nous pouvons utiliser ce composant pour compléter l'effet de commutation de base entre les points multi-touch et plusieurs conteneurs. Mais que se passe-t-il si nous devons ajouter des effets d'animation en plus ? Regardons d'abord le code d'implémentation de l'onglet de classe héritée :
On peut constater que j'ai exécuté la méthode setInterface après la méthode show. La méthode du même nom dans la classe abstraite sera appelée par défaut. Cette méthode d'interface est conçue pour ajouter des classes d'effets interactifs supplémentaires pour des lignes interactives similaires. Par exemple : maintenant nous voulons gérer l'effet d'un slideTab, il nous suffit alors d'hériter d'une classe d'application basée sur xTab, de remplacer la méthode setInterface et d'ajouter une classe d'animation pour obtenir l'effet de diapositive et c'est tout !
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:fonction (cible, navire){
this.parent (cible, navire);
this.anim(navire);
},
anim:fonction(navire){
...
}
});
Pour être honnête, il s'agit d'une idée de conception très grossière, mais elle nous permet de penser au mode de codage des composants sous un angle différent. Ce ne sont que quelques tentatives d'application superficielles, et l'excitation continuera... vous attend !
Réimpression : http://ued.alipay.com/2010/06/proposed-front-end-ui-components-and-then-build-a-new-train-of-thought/
AP.widget.xTab = AP.widget.basic.extend({
bindEvents:fonction (cible, navire){
E.on(target,this.options.eventType,this.action,target,this);
E.on(window,'load',this.oXtab,target,this);
},
action:fonction(e,cible){
this.switchTab(e,cible);
},
switchTab:fonction(e,cible){
...
pour(i=0,len=tabs.length;i<len;i++){
var hash = tabs[i].href.split("#")[1];
var vaisseau = D.get(hash + 'Extend');
si (navire) {
this.hide(navire);
}
D.removeClass(tabs[i].parentNode,'current');
if(target.href == tabs[i].href){
D.addClass(target.parentNode,'current');
si (navire) {
this.show(navire);
}
//Définir diverses interfaces d'application
this.setInterface (cible, navire);
}
E.preventDefault(e);
}
},
showTab : fonction (index) {
...
},
//Initialiser l'onglet de positionnement
oXtab:fonction(cible,e){
...
}
});
AP.widget.basic = nouveau AP.Class({
setOptions:fonction(options){
//Paramètres de l'interface
},
initialiser:fonction(cibles,options){
//Méthode d'initialisation, le but est d'établir l'association entre les éléments du sous-ensemble cible et une méthode
},
getVessel:fonction(cible){
//Obtenir le conteneur qui satisfait la relation de mappage cible
},
bindEvents:fonction (cible, navire){
// Lier l'action de déclenchement de la cible ici
},
action:fonction(){
//La fonction d'exécution déclenchée par l'événement lié à la cible contient la logique que vous souhaitez exécuter.
},
show:fonction(){
//afficher le conteneur
},
cacher:fonction(){
//masquer le conteneur
},
setInterface:fonction(){
//Définit l'interface partagée par chaque composant
}
})