What is a front-end template? Introduction to the principle of front-end templates and examples

Source: Internet
Author: User
Tags hasproperty parse string php template java web
What is a front-end template? How is the front-end template implemented? Many friends may not understand this, then, the following article will introduce you to the front-end template and the principle of simple implementation code.

Development of front-end templates

A template can be said to be one of the most frequently contacted tools in front-end development. The page fixed content is extracted into a template, the dynamic data returned by the server is loaded into the pit bits reserved in the template, and finally assembled into a full page HTML string to the browser to parse.

Templates can greatly improve development efficiency if no template developer is afraid to manually spell strings.

var tpl = ' <p> ' + user.name + ' </p> '; $ (' body '). Append (TPL);

In the development of the front-end in recent years, the template also follows the changes:

1. PHP Template jsp template

In the early days there was no back-end separation era, and the front end was just a folder in the backend project, with PHP and Java providing their own template engine. Take JSP as an example: a Java Web Application page is usually a. jsp file, this file content is most of the HTML and some of the template comes with syntax, essentially plain text, but neither HTML nor java.

JSP syntax: index.jsp


The template engine for this period is often the server that compiles the template strings , generating HTML strings to the client.

2. Handlebar Mustache Universal Template

09 node release, JavaScript can also be used to implement the functions of the server, which greatly facilitates the development staff. The birth of the mustache and handlebar templates facilitates front-end developers, both of which are implemented using JavaScript, which can be run either on the server or on the client side . But most of the usage scenarios are JS based on the data that the server asynchronously gets into the template, generating a new DOM to insert the page number. Very advantageous for front-end backend development.

Mustache Syntax: Index.mustache

<p>username: {{user.name}}</p>{{#if (User.gender = = = 2)}    <p> female </p>{{/if}}

3. Jsx in the template react in Vue

Next generation, the template notation in Vue is different from the previous template and is more powerful. Can be used both on the client and on the server side, but the use of the scene is very large: the page tends to change according to the data, the template generated by the DOM changes, which for the performance requirements of the template is very high.

Vue Syntax: Index.vue

<p>username: {{user.name}}</p><template v-if= "user.gender = = = 2" >    <p> female </p></ Div>

Features of the template implementation

Whether it's a template from JSP to Vue, the template is more and more simple and richer in syntax, but the basic functionality is not minimal:

    1. Variable output (escaped/not escaped): For security reasons, the template basically defaults to the string escape output of the variable, but also implements the function of not escaping the output, use cautiously.

    2. Conditional judgment (if else): features that are often needed in development.

    3. Loop variable: A loop array that generates a lot of duplicate code fragments.

    4. Template nesting: With template nesting, you can reduce a lot of duplicate code and Nest template integration scopes.

The above functions basically cover the basic functions of most templates, and for these basic functions you can explore how templates are implemented.

Template Implementation principle

As the title says, templates are essentially plain text strings, and how does a string manipulate the JS program?

On the template usage:

var domstring = template (templatestring, data);

The template engine obtains the scope of the template string and template, which is compiled to generate the full DOM string.

Most of the template implementation principles are basically consistent:

Template strings are first stripped out of ordinary strings and template syntax strings by various means to generate an abstract syntax tree ast; then compile for the template syntax fragment, and the template variables are searched for variables in the engine input, and the template syntax fragment produces a plain HTML fragment that is stitched out with the original normal string.

In fact, the template compilation logic is not particularly complex, as the Vue dynamic binding data template has time to refer to the end of the link.

Quickly implement a simple template

Now take the mustache template as an example and manually implement a template that implements the basic functionality.

Template string Template: Index.txt

<! DOCTYPE html>

Template corresponding data:

Module.exports = {  common: {    username: ' Aus ',    escape: ' <p>Aus</p> '  },  Shouldescape: False,  list: [    {key: ' A ', value:1},    {key: ' B ', value:2},    {key: ' C ', value:3},    {key: ' d ', value:4}< c10/>]};

How to use the template:

var fs = require ("FS"), var TPL = Fs.readfilesync ('./index.txt ', ' UTF8 '), var state = require ('./test '); var Panda = require ( './panda '); Panda.render (TPL, State)

Then to implement the template:

1. Regular cut string

After the template engine gets to the template string, it is common to use regular cut strings to distinguish between static strings, those that need to be compiled, and an abstract syntax tree (AST).

The unhandled string is participle, forming a character group TokensPanda.prototype.parse = function (TPL) {  var tokens = [];  var tplstart = 0;  var tagstart = 0;  var tagend = 0;  while (Tagstart >= 0) {    Tagstart = Tpl.indexof (Opentag, tplstart);    if (Tagstart < 0) break;    Plain text    Tokens.push (new Token (' Text ', Tpl.slice (Tplstart, Tagstart)));    Tagend = Tpl.indexof (Closetag, Tagstart) + 2;    if (Tagend < 0) throw new Error (' {{}} tag not closed ');    Subdivide js    var tplvalue = tpl.slice (Tagstart + 2, tagEnd-2);    var token = THIS.CLASSIFYJS (tplvalue);    Tokens.push (token);    Tplstart = Tagend;  }  Last paragraph  tokens.push (new Token (' Text ', Tpl.slice (Tagend, Tpl.length)));  return This.parsejs (tokens);};

This split-string is usually done using regular methods, and retrieving the strings later is a significant use of the regular method.

In this step you can usually check out the template label closure exception, and error.

2. Classification of template syntax

After generating the AST, the normal string does not need to be re-tube, and it will output directly, focusing on the classification of the template syntax.

Specifically handles JsPanda.prototype.parseJs = function (tokens) {var sections = [] in the template;  var nestedtokens = [];  var conditionsarray = [];  var collector = Nestedtokens;  var section;  var currentcondition;    for (var i = 0; i < tokens.length; i++) {var token = tokens[i];    var value = Token.value;    var symbol = Token.type;        Switch (symbol) {case ' # ': {collector.push (token);        Sections.push (token);        if (token.action = = = ' Each ') {collector = Token.children = [];          } else if (token.action = = = ' if ') {currentcondition = value;          var Conditionarray;          Collector = Conditionarray = []; token.conditions = Token.conditions | |          Conditionsarray;        Conditionsarray.push ({condition:currentcondition, collector:collector});      } break; } case ' Else ': {if (sections.length = = = 0 | | sections[sections.length-1].action!== ' if ') {throw n EW error (' Else use errorError ');        } currentcondition = value;        Collector = [];        Conditionsarray.push ({condition:currentcondition, collector:collector});      Break        } case '/': {section = Sections.pop ();        if (section && section.action!== token.value) {throw new Error (' directive tag not closed ');          } if (Sections.length > 0) {var lastsection = sections[sections.length-1];          if (lastsection.action = = = ' Each ') {collector = Lastsection.chidlren;            } else if (lastsection.action = ' if ') {conditionsarray = [];          Collector = Nestedtokens;        }} else {collector = Nestedtokens;      } break;        } default: {Collector.push (token);      Break }}} return nestedtokens;}

In the previous step, we generated the AST, which is here as an array of tokens for the word breaker:

[Token {}, token {},    token {},]

This token is a string of tokens, respectively, the type of token, action, sub-token, conditional token and other information.

The/** * Token class represents the standard data structure for each word breaker */function Token (type, value, action, children, conditions) {  this.type = type;  This.value = value;  This.action = action;  This.children = children;  This.conditions = conditions;}

In this step, the child tokens in the loop method are nested into the corresponding token, and the conditional render token is nested into the corresponding token.

After this step is complete, a standard AST with nested relationships is complete.

3. Variable Lookup and Assignment

Now it's time to find the corresponding value based on the variables in token and generate a worthwhile string based on the corresponding function.

/** * Parsing data structure of class */function Context (data, parentcontext) {this.data = data;  This.cache = {'. ': This.data}; This.parent = Parentcontext;} Context.prototype.push = function (data) {return new Context (data, this);}  Finds the true variable value based on the string name Context.prototype.lookup = function Lookup {name = Trim (name);  var cache = This.cache;  var value;  Query over Cache if (Cache.hasownproperty (name)) {value = Cache[name];    } else {var context = This, names, index, lookuphit = false;        while (context) {//User.username if (Name.indexof ('. ') > 0) {value = Context.data;        names = Name.split ('. ');        index = 0;  while (value! = NULL && index < names.length) {if (index = = = names.length-1) {Lookuphit          = Hasproperty (value, Names[index]);        } value = value[names[index++]];        }} else {value = Context.data[name];      Lookuphit = Hasproperty (context.data, name);     } if (Lookuphit) {   Break    } context = Context.parent;  } Cache[name] = value; } return value;

In order to improve the efficiency of the search, the cache proxy is used, each time the variable storage path is found to facilitate the next quick lookup.

Unlike the JavaScript compiler, the template engine cannot find the corresponding variable when looking for a variable, which terminates the lookup, and returns null without an error.

4. Conditional rendering and nesting of nodes

Here the template syntax token and the ordinary string token are started to compile the generated string uniformly and stitch it into a complete string.

Panda.prototype.renderTokens = function (tokens, context) {  var result = '  ) based on tokens and context mixed stitching string output var token, symbol, value;  for (var i = 0, numtokens = tokens.length; i < Numtokens; ++i) {    value = undefined;    token = tokens[i];    symbol = Token.type;    if (symbol = = = ' # ') value = this.rendersection (token, context);    else if (symbol = = = ' & ') value = This.unescapedvalue (token, context);    else if (symbol = = = ') value = This.escapedvalue (token, context);    else if (symbol = = = ' text ') value = This.rawvalue (token);    if (value!== undefined) result + = value;  }  return result;}

5. Drawing the page

The page string has been parsed and can be output directly:

Panda.prototype.render = function (TPL, state) {  if (typeof TPL!== ' string ') {    return new Error (' Please enter string! ');  }  Parse string  var tokens = This.cache[tpl]? Tokens:this.parse (TPL);  Parsing data structure  var context = State instanceof Context State:new context (state);  Render Template  return This.rendertokens (tokens, context);};

When the output page string is parsed by the browser, the page appears.

The above is just a simple template implementation, and has not been tested by the system, only for learning to use, the source of the portal. Mature template engine is full of exception handling, variable lookup parsing, scope substitution, optimization rendering, breakpoint debugging and other functions.

Summarize

Front-end templates This piece can do a lot of things, many frameworks are integrated template functions, with Css,js and other mixed compilation generated Dom parsing good style and binding success events.

In addition, there are many ways to implement the template, the implementation of this article refers to the mustache source code, template tags within the tag is parsed, but is through the code snippet classification, variable lookup way to execute, the code of the pure string into the code executed by the interpreter.

In addition to the Vue this can achieve two-way binding template can take a look at the time.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.