Recently, I read the article "New Ideas for Building Front-End UI Components" written by Uncle Yu, which reminded me of an article I shared last year , "JS Design Pattern for Collaborative Development with Feelings" , which resonated a bit...
It is said that in the new version of Alipay's cashier project last year, I tried this component coding model for a while. Here is a little bit of experience to share with you:
Looking back at the abstract class mentioned before, students who know something about design patterns may find it familiar. Yes, at first glance, it looks like an abstract factory, but combined with the following basic classes, you will find that I did not override getVessel, show, hide and other methods in each basic class, but directly inherited these methods in the abstract class. There will definitely be people who don't understand why they do this. It's just because it's JS, not JAVA. A certain degree of coupling in exchange for sufficient flexibility is not excessive in my opinion, not to mention that this abstract class must ensure absolute stability. It is necessary that it is not allowed to be modified at will after it is formed.
Through this abstract class, I associate a contact object with a container object, and implement the simplest interaction between them through the action method. "The simplest" means nothing more than display or hide operations, so I defined the show and hide methods. Obviously the "simplest" interaction behavior cannot satisfy 100% of user behavior, so I must set a setInterface method and add effect classes to classes that require special interaction effects. Finally, avoid directly instantiating this abstract class when using it. Remind everyone in the action method that if you want to instantiate an operation, please go to a specific inheritance class to override the action method.
Through this abstract class, we can inherit the most basic aPop, dropDown, xbox, xTab and other components... These have already been mentioned in the previous p article. I won’t go into details here. I will focus on explaining that when the basic classes written here cannot meet the special needs. , how can we quickly develop personalized components.
Let's take xTab as an example. We can use this component to complete the basic switching effect between multi-touch points and multiple containers. But what if we need to add some animation effects on top of this? Let’s first look at the implementation code of the inherited class tab:
It can be found that I executed the setInterface method after the show method. The method of the same name in the abstract class will be called by default. This interface method is designed to add additional interactive effect classes for similar interactive lines. For example: now we want to deal with the effect of a slideTab, then we only need to inherit an application class based on xTab, override the setInterface method, and add an animation class to achieve the slide effect and that's it!
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:function(target,vessel){
this.parent(target,vessel);
this.anim(vessel);
},
anim:function(vessel){
...
}
});
To be honest, this is a very crude design idea, but it allows us to think about the coding mode of components from a different angle. The above are just some superficial application attempts, and the excitement will continue...waiting for you!
AP.widget.xTab = AP.widget.basic.extend({
bindEvents:function(target,vessel){
E.on(target,this.options.eventType,this.action,target,this);
E.on(window,'load',this.oXtab,target,this);
},
action:function(e,target){
this.switchTab(e,target);
},
switchTab:function(e,target){
...
for(i=0,len=tabs.length;i<len;i++){
var hash = tabs[i].href.split("#")[1];
var vessel = D.get(hash + 'Extend');
if(vessel){
this.hide(vessel);
}
D.removeClass(tabs[i].parentNode,'current');
if(target.href == tabs[i].href){
D.addClass(target.parentNode,'current');
if(vessel){
this.show(vessel);
}
//Set various application interfaces
this.setInterface(target,vessel);
}
E.preventDefault(e);
}
},
showTab: function(index){
...
},
//Initialize positioning tab
oXtab:function(target,e){
...
}
});
AP.widget.basic = new AP.Class({
setOptions:function(options){
//Interface settings
},
initialize:function(targets,options){
//Initialization method, the purpose is to establish the association between targets subset elements and a method
},
getVessel:function(target){
//Get the container that satisfies the target mapping relationship
},
bindEvents:function(target,vessel){
//Bind the trigger action of target here
},
action:function(){
//The execution function triggered by the event bound to the target contains the logic you want to execute.
},
show:function(){
//display container
},
hide:function(){
//hide container
},
setInterface:function(){
//Set the interface shared by each component
}
})