Recentemente, li o artigo "Novas ideias para construir componentes de UI front-end" escrito por Tio Yu, que me lembrou de um artigo que compartilhei no ano passado , "JS Design Pattern for Collaborative Development with Feelings" , que ressoou um pouco. .
Diz-se que na nova versão do projeto de caixa do Alipay no ano passado, experimentei este modelo de codificação de componentes por um tempo. Aqui está um pouco de experiência para compartilhar com vocês:
Olhando para trás, para a classe abstrata mencionada anteriormente, os alunos que sabem algo sobre padrões de projeto podem achá-la familiar. Sim, à primeira vista parece uma fábrica abstrata, mas combinada com as classes básicas a seguir, você descobrirá que não a substituí. getVessel, show, hide e outros métodos em cada classe básica, mas herdou diretamente esses métodos na classe abstrata. Definitivamente haverá pessoas que não entendem por que fazem isso. É só porque é JS, não JAVA. Um certo grau de acoplamento em troca de flexibilidade suficiente não é excessivo na minha opinião, sem falar que esta classe abstrata deve garantir estabilidade absoluta. É necessário que não possa ser modificada à vontade depois de formada.
Através desta classe abstrata, associo um objeto de contato a um objeto contêiner e implemento a interação mais simples entre eles por meio do método de ação. "O mais simples" significa nada mais do que operações de exibição ou ocultação, então defini os métodos de exibição e ocultação. Obviamente, o comportamento de interação "mais simples" não pode satisfazer 100% do comportamento do usuário, então devo definir um método setInterface e adicionar classes de efeitos às classes que requerem efeitos de interação especiais. Finalmente, evite instanciar diretamente esta classe abstrata ao usá-la. Lembre a todos no método de ação que se você deseja instanciar uma operação, vá para uma classe de herança específica para substituir o método de ação.
Através desta classe abstrata, podemos herdar os componentes mais básicos do aPop, dropDown, xbox, xTab e outros... Estes já foram mencionados no artigo anterior, não vou entrar em detalhes aqui. quando as classes básicas escritas aqui não atendem às necessidades especiais, como podemos desenvolver componentes personalizados rapidamente.
Tomemos xTab como exemplo. Podemos usar este componente para completar o efeito básico de alternância entre pontos multitoque e vários contêineres. Mas e se precisarmos adicionar alguns efeitos de animação em cima disso? Vejamos primeiro o código de implementação da guia da classe herdada:
Pode-se descobrir que executei o método setInterface após o método show. O método de mesmo nome na classe abstrata será chamado por padrão. Este método de interface foi projetado para adicionar classes de efeitos interativos adicionais para linhas interativas semelhantes. Por exemplo: agora queremos lidar com o efeito de um slideTab, então só precisamos herdar uma classe de aplicação baseada em xTab, substituir o método setInterface e adicionar uma classe de animação para obter o efeito de slide e pronto!
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:function(alvo,navio){
this.parent(alvo,navio);
this.anim(vaso);
},
anim:function(vaso){
...
}
});
Para ser honesto, esta é uma ideia de design muito rudimentar, mas nos permite pensar sobre o modo de codificação dos componentes de um ângulo diferente. O que foi dito acima são apenas algumas tentativas superficiais de aplicação, e a emoção continuará... esperando por você!
Reimpressão: 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:function(alvo,navio){
E.on(target,this.options.eventType,this.action,target,this);
E.on(janela,'carregar',this.oXtab,target,this);
},
ação:função(e,alvo){
this.switchTab(e,alvo);
},
switchTab:função(e,alvo){
...
for(i=0,len=tabs.length;i<len;i++){
var hash = tabs[i].href.split("#")[1];
var navio = D.get(hash + 'Estender');
if(navio){
this.hide(vaso);
}
D.removeClass(tabs[i].parentNode,'atual');
if(target.href == guias[i].href){
D.addClass(target.parentNode,'atual');
if(navio){
this.show(vaso);
}
//Definir várias interfaces de aplicação
this.setInterface(alvo,navio);
}
E.preventDefault(e);
}
},
showTab: função(índice){
...
},
//Inicializa guia de posicionamento
oXtab:função(alvo,e){
...
}
});
AP.widget.basic = novo AP.Class({
setOptions:função(opções){
//Configurações de interface
},
inicializar:function(destinos,opções){
//Método de inicialização, o objetivo é estabelecer a associação entre os elementos do subconjunto alvo e um método
},
getVessel:função(destino){
//Obtém o contêiner que satisfaz o relacionamento de mapeamento de destino
},
bindEvents:function(alvo,navio){
// Vincule a ação de gatilho do alvo aqui
},
ação:função(){
//A função de execução acionada pelo evento vinculado ao destino contém a lógica que você deseja executar.
},
mostrar:função(){
//mostra o contêiner
},
ocultar:função(){
//oculta o contêiner
},
setInterface:função(){
//Define a interface compartilhada por cada componente
}
})