The template engine is responsible for assembling data and presenting it in another form or appearance. The page in the browser is the final rendering of the Web template engine.
Whether you use the template engine directly or not, Web templates have always been there, not at the front end but at the back end, and its appearance can even be traced back to the formal establishment of the HTML standard of Hypertext Markup Language.
Server-side template engine
The earliest Web template engine I know is PHP, which was officially born in 1997 and works on the server side. Let's take a look at the official introduction of PHP-what is:
HPer generally agrees that PHP itself is the most natural and native PHP template engine, because it is. In the world of PHP, repackaged template engines have appeared many times, and the famous one is smarty.
Many other server-side languages have HTML template engines, such as JSP and mustache.
Undoubtedly, the final result generated by these server-side template engines is HTML(XML) strings, and the processing flow logic is realized by using the grammar of the host language itself.
Their * * * characteristics are the same: HTML is just a string, and the final result may need a cleaning or correction verification tool like Tidy.
Here is a question: Is it necessary for smarty to exist in secondary packaging?
Browser-side template engine
The earliest front-end template engine I know is jCT, which was hosted by Google Code and was born in 2008. The host language is JavaScript, which runs in the browser.
Today, search for JavaScript template engine in OSC, and you will get 100+ results. Here are some examples:
Lightweight: tpl.js, T.js
Cognition: arttemplate, mustache.js, doT.js, handlebars.js, pug.
DOM tree-based: domTemplate, transparency, chart
Based on VDOM: htmltemplate-vdom, virtual-stache, html-patcher.
Popular frameworks: Vue.js, ReactJS, riot
The real world: PowJS
Their * * * characteristics are the same: they all support interpolation.
There is also a comparison of template engine popularity, and even the reasons and advantages and disadvantages of voting for the best JavaScript template engine.
How to choose
I think existence is reasonable, and every engine and framework always has its merits, at least in your application, in a certain era, so this article will not comment on what is wrong with an engine, which is not objective. Now answer the question mentioned earlier: Is smarty necessary to exist? My answer is: Yes. The reason is simple, it depends on who you use and the background. For the front-end and back-end are not separated, or the front-end personnel are not familiar with the back-end language, or because of their job responsibilities, it is realistic for the front-end personnel to master a more general template grammar (language). On the contrary, letting PHPer use smarty by himself will waste skills.
The following are general suggestions for engine selection:
The premise is that the selected engine can meet the data rendering requirements and does not conflict with the existing dependencies. If you are already very familiar with an engine, then you already have the answer.
Is it a one-time project requirement? If yes, directly choose the lightweight with the lowest learning complexity. Do you want to do component development?
The engine supports precompiled results. Don't you compile in real time every time?
Cross platform? If there is official support, reactive JSX engine or pure VDOM engine is the first choice.
Choose the one with the lowest learning or maintenance complexity. As we all know, developers hate that debugging takes more time than writing code.
Finally, the performance comparison. Performance comparison is a very detailed work, and the comparison results of others may not be consistent with your scene.
I think the contrast of grammatical styles should be weakened. Preference is incomparable, and some grammars even have special background reasons.
Why is it the final performance comparison?
Performance is really important, but if performance has not affected your application experience, then ignore it. It is very difficult to simulate the application scenario, and it can only be tested through the real scenario, but the current testing tools can't achieve this effect.
Some of the above questions have fixed answers. Let's discuss the remaining questions: how to consider component development, precompiling support and complexity?
Component development
Developing components is no longer a question of choosing a template engine, but a question of choosing an ecological environment. If your application needs to be completed faster, then time is the first priority, so choose a popular framework with enough components for you to use or refer to. If your application has an independent ecological environment and needs long-term maintenance technology selection, then continue reading below.
Precompiling
Precompilation should have:
The compiled result does not need the compilation process in the target environment.
The compiled results can be debugged, which means that the results should contain native ECMAScript code instead of pure data description.
Everyone knows that React-JSX supports precompiling. Officially, React does not have JSX, which means that it has always been build.
Some engines based on string processing also support precompiling. If precompiling is needed, it is suggested to abandon the engine whose compilation results are still based on string concatenation, and it is better not to precompile, which is a technical means before HTML5 is widely supported.
You must have at least a compilation result like React-JSX to debug. Note: Vue.js supports multiple template engines, which can achieve the same effect.
Original ReactJS code, in which Web component technology is used:
Class HelloMessage extends React. Component {
render() {
Return & ltp> Hello & ltx-search & gt;; { this . props . name } & lt; /x-search & gt; ! & lt/p & gt; ;
}
} After compilation:
Class HelloMessage extends React. Component {
render() {
Return React.createElement (
“p”,
Empty,
"hello",
React.createElement(
"x search",
Empty,
This. Prop. Name
),
"!"
);
}
Many VDOM engines can also compile similar effects, such as htmltemplate-vdom.
& lt script & gt
var id = 3;
var env = {
Character: [
{
id: 'id 1 ',
Name: "John"
Internal: [{ title: 'a 1'}, {title: 'b 1' }],
City: new york,
Activity: Really
},
{
id:“id2”,
Name: "Mary"
Internal: [{ title: 'a2'}, {title: 'b2' }],
City: "Moscow"
}
],
githubLink:“/agent Cooper/html template-vdom”,
ItemClick: function (id) {
env . people . foreach(function(person){
person . active = String(person . id)= = = String(id);
});
loop . update(env);
}
//Omit ....
};
& lt/script & gt; complexity
It is difficult to judge which of the two engines has low complexity by the only standard, which is caused by the different thinking modes of users. For example, the engines listed above, different users have different feelings about the difference between using and precompiling results, which is the rationality and value of the existence of different engines.
Some users think that this application scenario with string template meets the demand and is light enough.
Some users think that the template engine of string splicing technology is not powerful enough and has no sense of the times.
Some users think that OOP is rational, logical and abstract.
Some users think that native HTML is the front end.
Some users think VDOM is more suitable.
These judgments have their own reasons, with different emphases and different standards. But we can still consider their complexity from their * * *.
String class templates are usually lightweight and beyond the scope of this section. What is the criterion for judging the complexity of non-string templates? I think we can consider the complexity of data binding.
The data binding mentioned in this paper is not only interpolation, but also context and events, even the host environment of the whole runtime.
In fact, at least one VDOM-level engine is needed to have this ability, because VDOM can be mapped to real DOM nodes.
There are probably several modes (combinations):
1. The entry parameter is an object, and the variable x in the template is. The x property of the object, such as virtual-cache-example.
2. Specific syntax or attributes, such as ... of Vue.js, attributes and methods of calculation.
3. Abstract semantic attributes, such as the word "initiative" in Vue.js, are suitable for various scenarios, easy to understand and will not cause ambiguity.
4. Not responsible for binding, users need to be very familiar with native methods and bind with native methods, such as PowJS.
These patterns are only theoretical, and they are usually the problems that template engine designers have to solve. Users had better ask directly:
1. Can you write the simplest console.log(context) directly in the HTML template for debugging?
2. Can you bind or pass different context parameters in a multilevel DOM tree?
3. Can the generated nodes be accessed upward in the inner layer of the multi-layer DOM tree?
The template engine team will give you the right solution, but it is usually different from the literal goal. I think this is the key to your judgment and choice, and it is your recognition of the correct method given by the official.
Embedded in DOM
Embedded in HTML
PowJS is implemented like this:
Instructions that the implementation template must implement.
Precompile and output native ECMAScript code
The grammatical structure of the template is consistent with the writing of ECMAScript function.
Finally, writing PowJS template is just like writing ECMAScript function.
Writing GoHub index.
& lt template & gt
& ltdetails func = " repo " param = " data " if = " is . object(data . content)& amp; & amp! sel(` # panel details[sha = ' $ { data . sha } ']`),"
open
let="ctx=data.content "
sha="{{data.sha}} "
origin="{{ctx。 Buy back}} "
repo = " { { data . owner } }/{ { data . repo } } "
subdir="{{ctx。 Subdir||''}} "
filename="{{ctx。 File name}} "
render=":ctx "
do = " this . renew(sel(` # panel details[repo = ' $ { data . owner }/$ { data . repo } ']`) "
break
& gt
& lt summary & gt{{ctx. Description}} & lt/summary & gt;;
& ltp if = " ':';" each="ctx。 Package, val-pkg ">
& ltp title="{{pkg。 Progress }}: {{pkg. Summary}} "& gt{{pkg. Import}} & lt/p & gt;;
& lt/p & gt;
& lt/details & gt;
& ltdl func="list" param="data "
if= "! sel(` # panel details[sha = ' $ { data . sha } ']`)& amp; & amp':'||'';"
each="data.content,data.sha,val-rep "
do = " this . appendto(sel(' # panel ')" & gt;
& lt details sha = "{{sha}}" repo = "{{rep.repo}}" >
& lt summary & gt {{rep.synopsis}}</summary >
& lt/details & gt;
& lt/dl & gt;
& lt/template & gt; Most template engines implement these instructions, such as if and each. In the PowJS template above, there are:
The global object is sel.
Templates (functions) are named repo and list.
Template (Function) Input Parameter Data
Custom local variable ctx
Derivation of data formal parameters of lower template (function). sha->; Stellar hour angle
Traversal value (CTX) derived from formal parameters of lower-level templates. Package, val-pkg)->; pkg 、( data.content,val-rep)-& gt; represent
DOM nodes operate this.renew, this.appendTo and render directly to the page DOM tree.
Process control interrupt
Pseudo node if = "':';" When rendering, P nodes are not generated at all. It is a pseudo node, which is equivalent to the block code symbol "{}".
The key point is that the whole template structure, instruction semantics and ECMAScript function are completely consistent:
There is no data binding. You wrote an ECMAScript function. Just pass the parameters. What binding do you want?
Without event binding, every node is real. Just write addEventListener directly.
To debug, just find a do or if or let and insert _=console.log(x). Comma expressions can be seamlessly inserted into almost all native statements.
All business logic is written by users themselves, and PowJS is only responsible for pasting it into a function.
The export view is ECMAScript source code, and the following figure is taken from demo My Folders.
So PowJS is the final choice? PowJS's ideas are native, native DOM and native ECMAScript.
Native is also a problem of PowJS. Not all users like native. I believe some users prefer abstract style. Indigenous people always have a little "primitive" in their eyes.
Native means that you can extend and introduce other libraries to match, but PowJS will never have a watcher implemented by define setter/getter, which is beyond the scope of the template engine. If there is, it must be an independent project.
Finally, my view is still: your needs are the key to choosing a template, and the one that suits you is good.