⬆️ ⬇️

How to untangle noodles without falling into depression

This article is not about your sweet interfaces on the reactor, angular or what are you using? This article is about those situations where you have a bunch of jQuery noodles. No, let it be mountains of jQuery noodles wrapped in backbone view.



This article uses the Backbone.View.Elements library.



Problem one: low expressive selectors



We all saw noodles, we all know: noodles in JSe - probably not all is well in the layout. And if everything is so, then the code is likely to be full of obscure manipulations with the house. It is difficult to read such a code, because it’s necessary, without losing the author’s thoughts about what is happening here at all, to keep in mind a bunch of vague names for the elements. So let's add some expressiveness to the code:

_selectors: function () { return { elemName: '.block__elem-name' }; } 
We will add all the selectors in one place and give a clear name to the elements for the selection of which they are needed. By the way, we will choose them like this:

 this._elem('elemName'); 
instead

 this.$('.block__elem-name'); 




In our case, you can say that this added little expressiveness, but do not forget that your project most likely is not a project that uses BEM for class naming, but sweet-smelling over-semantic selectors of the form.

 'div > tr.row[data-active=”true”] a.red-Button' 
for “buy” buttons.

')

In addition to the ability to select an element inside our view, we also had the opportunity to get the selector itself by name:

 this._selector('elemName'); 
This is also necessary.



Another advantage is that if the layout changes, we will only need to change the selector in one place, because we have reduced duplication of code.



Problem two: storing items



You know, it happens like this:

 $('div > tr.row[data-active=”true”] a.red-Button').blahBlah(); 
and after 10 lines like this:

 $('div > tr.row[data-active=”true”] a.red-Button').anotherBlahBlah(); 


Tearing away the palm from the face, you will bring it into the variable

 var $buyButton = $('div > tr.row[data-active=”true”] a.red-Button'); 
oh no, you have the same Backbone - bring it to the property

 this._$buyButton = this.$('div > tr.row[data-active=”true”] a.red-Button'); 
or have you already connected Backbone.View.Elements?

 this._$buyButton = this._elem('buyButton'); 


You really shouldn't - _elem caches it all, so just

 this._elem('buyButton'); 


Caches, speak? And what if everything changes?



Yes, we also heard that there are two problems in programming. therefore

 this._findElem('elemName'); 
searches without using cache

 this._dropElemCache('elemName'); 
cleans the cache for a particular item, and

 this._dropElemCache(); 
cleans your entire cache to shine when you realize that the time has come. For example, after rendering.



Global elements



We also wrapped the most frequently used elements in jQuery so as not to do this more than once in an application. Meet:

 this._$window; this._$body; this._$document; 




Problem three: imperative styles



It seems that there is a whole language to describe styles, but no - now and then you can find dyes in noodles:

 $('div > tr.row[data-active=”true”] a.red-Button').css({color: 'magenta'}); 
Rather pepper everything with declarativeness and mix well with CSS:

 .button_active { color: magenta; } 
We’ve taken care of class manipulation. First, we denote all classes in one place:

 _classes: function () { return { activeButton: 'button_active' }; } 
And then you want - add a class

 this._addClass('activeButton', 'buyButton'); 
want - delete:

 this._removeClass('activeButton', 'buyButton'); 
want - switch:

 var condition = !!Math.round(Math.random()); this._toggleClass('activeButton', 'buyButton', condition); 


You can get a selector if the class is already described:

 this._selector('activeButton'); // returns '.button_active' 
or you can search for items:

 this._elem('activeButton'); 
Just do not forget about the cache, because the active button probably changes

 this._findElem('activeButton'); 


The fourth problem: when everything is difficult



Sometimes, selectors and classes are formed dynamically:

 var id = 5, state = 'highlighted'; $('.item[data-id=”' + id + '”]').addClass('item_state_' + state); 
This is where complex selectors come into play:

 _classes: function () { return { itemInState: 'item_state_%s' }; }, _selectors: function () { return { itemById: '.item[data-id=%s]' }; } 
Then the following will be true:

 this._class('itemInState', 'highlighted'); //  'item_state_highlighted' this._selector('itemInState', 'highlighted'); //  '.item_state_highlighted' this._selector('itemById', 5); //  '.item[data-id=5]' 


And the manipulation described above will be performed as follows:

 var id = 5, state = 'highlighted'; this._addClass(['itemInState', state], ['itemById', id]); 
The item_state_highlighted class will be added to the element found by the .item selector [data-id = 5]



Terminal complexity of selectors



 _classes: function () { return { item: 'item_%(mod)s_%(value)s' }; } 
Each place has its own name

 this._elem('item', { mod: 'state', value: 'focused' }); 
Find a jQuery collection by '.item_state_focused'



Fifth problem: data acquisition



A little sugar for date attributes.

 this._data; 
It stores the data of the root element of the view. So if you have a div

 <div data-some-ids=”[5,6,7]”></div> 
on which the view is initialized

 this._data['someIds']; //   [5,6,7] 
And if the data is stored in a specific element, then it will help you.

 this._getElemData('elemName', 'someIds'); 
To get all the data:

 this._getElemData('elemName'); //  {someIds: [5,6,7]} 




Pro installation and use



GitHub: github.com/backbonex/backbone.view.elements

todomvc using and without Backbone.View.Elements

Source: https://habr.com/ru/post/249373/



All Articles