Recently, the most rapid development of prototypes of web applications is increasingly required. Interfaces become more complex, a huge amount of data is required. And so I was puzzled by the creation of an easy and simplest html template. Who cares what happened on ~ 50 lines of the JS code - under cat.
Minimum task
To make one-sided (JS → HTML) template engine that links JS data with html mapping is as simple as possible. The solution should be fast, with a minimum threshold of entry - anyhow and ready. Maximum dopilivaemosti under specific requirements - the primitiveness of success.
Principle of operation
From the html side
We will write the usual html code, where the usual data-attributes will be used to communicate with js:
data-template - the content that will be displayed inside the tag
data-namespace - data that is bound to JS
JS side
Data should be recorded and updated transparently. Those. if we have an object object with the data property, then this one should be updated in html immediately after the usual one:
')
object.data = 5;
Without any auxiliary methods like:
object.setData = function(val){ this.data = val; document.getElementById("tpl").html = val; } object.setData(5);
- this is the norm approach, but what will you do if a large bundle of json data comes from the server, which you need to push to different objects and display the changes in the interface? I am tired of writing and calling my setter for each property / set of properties.
The solution is simple. For each property of the object, we can specify default setters / getters, which are triggered just by changing the value with the usual assignment. This is called
Object.defineProperty (...) - I will not retell the article, I’ll go straight to the idea.
We need to run through all the properties of the object that have a connection with html. There are two ways to do this:
1) Run through the dom, pulling out all the possible (non-duplicate) values of the data-namespace attribute in a separate array
2) For each object in js we will manually specify an array that says
which data (only what and not with what) will be used in the connections.
Since the code claims to be visual implementation and primitive - choose the second option.
In order not to beat around the bush, I will immediately give an example with explanations.
html <div data-template="dataA" data-namespace="test"> dataA this_namespace=test</div> <div data-template="dataB" data-namespace="test"> dataB this_namespace=test</div> <div data-template="dataA" data-namespace="test2"> dataA this_namespace="test2"</div>
js var obj1 = { this_namespace: 'test',
As you can see, initially there are no data in the object, we will get it later - to begin with, the object must be prepared for this.
Magic
All magic is to run inside the object through the this_data array and create 2 properties for each element of the array in the same object:
1) __dataA, __dataB ... - values will be stored here
2) dataA, dataB ... - and values will be stored here =)
The meaning of such a manipulation is that if we specify for example the default setter simply for the dataA property, which will write the transferred value here, it will turn out to be recursive. To avoid this, a separate property is created with the prefix "__" (any one can be, for example fake_ or magic_ - I just chose one so as not to clutter up the namespace of the object).
It turns out that when we write obj.dataA = 3, this value is written into the obj .__ dataA property, and the default getter will return obj .__ dataA when it is requested by obj.dataA. That is, in fact, in the obj array there are no dataA and dataB properties in their pure form at all - the setters and getters replace them with a property with a prefix.
As I said, you need to ensure that the threshold of entry is as low as possible so that it is easier for beginners. And who should be rewritten as they want. In this regard, the whole method of giving the object the desired look will be implemented through the object's prototype.
Here the code is inconvenient to read, so immediately look
here (jsfiddle) - there all the code with comments and start.
What else
- Not cross-browser, (ie11 +) because of the need to use let instead of var - so as not to bother with closures. But again - you can rewrite.
- Nested objects out of the box will not work - you can add. I gave only the most abbreviated code that can be customized.
- Following the concept that there should be no logic in html, I did not add the ability to use even primitive operations in templates (for example, dataA + dataB). Stupid data output. The logic should be on js. Although when I first started to do this, such an opportunity was and there I had to use eval quickly.
- There are no checks at all in the code; you do this yourself if necessary, just in my particular case for which this method was written, all checks go through another layer.
- As a consolation prize: at the beginning of the article I said that “when we’ve got a bunch of json daaaans, what can I do with them ...” - everything is simple: JSON parsim, push it into the necessary objects via Object.assign - will work.
- In my projects I name all variables and properties with a prefix - the data type. Something like arr_list = [1,2,3]; int_count = 2; etc. This allows me “to set default default getters to give a value corresponding to the data type, and if we have int_count = 1.4, we will return the result 1 and check all values on the fly. It disciplines and really helps.
- For each situation, you can provide different set and get, depending on what you want to get in the end - very good.
Ask, criticize, be healthy!