Portal: https://github.com/xiangyuecn/BuildHTML

Before Posting this article, I clicked on a similar template engine article on Nuggets and noticed that several words do not allow javascript in templates, but provide a list of functions…. BuildHTML allows you to use code that you can use. If you use registerHelper function, it is as complex as writing a wechat apet

What did copy say before

HTML does a little bit of work (nothing), and if you’re trying to generate HTML by hand, it’s easy to mess up your code, but if you use a template and parse it into HTML, it’s much easier.

Presentation: https://xiangyuecn.github.io/BuildHTML/

The following is copied from the README

BuildHTML is used for front-end HTML template parsing

This code has been used in several projects before (PC, mobile, Android, IOS Hybrid App). It is simple and lightweight, but the function is not simple at all. Less than 100 lines of code, Uglify compressed 1K size (optional remove _eval after 0.8K).

Demo address: xiangyuecn. Making. IO/BuildHTML /

Method of use

First, introduce code

Method 1: Copy the code directly into your project’s public JS file for use.

Second, analytical use

After introducing the code, two functions are available: BuildHTML and BuildHTMLArray.

  1. To define templates, it is recommended to use script text/template tags to wrap text data:
<script type="text/template" class="tp_action">
<div>{name} This is the first time to use the template, please give me more comments. ({:slogan}){{::html}}
</div>
</script>

<script>
var tp_action=$(".tp_action").html();
</script>
Copy the code
  1. Parsing the template
var data={name:"Doug".slogan:" "};
var html=BuildHTML(tp_action,data);

data.html="{fn:BuildHTMLArray.index}";
var list=[data,data,data];
html+=BuildHTMLArray(tp_action,list);
Copy the code
  1. The parsed data is displayed
$("body").append(html);
Copy the code

Template syntax

HTML template by embedding specific syntax to achieve automatic content generation.

All embedded code reads and writes o objects, which are the data objects that are passed in. ; If variable data needs to be passed between multiple embedded code blocks, it can be put into o objects.

Template embedding syntax supports two types:

{{}} : preprocessing syntax

This syntax is executed before the {} syntax to implement:

  • Executing complex code returns results
  • Dynamically generate {} syntax
  • Define the built-in template (since this is pre-processing, it doesn’t matter where the built-in template is defined)
  • Define functions and variables
  • . The role you want

This syntax can be written in three ways:

1. {{variable name = multiple lines of text}}

Defines a multi-line text variable with no return value. Typically used for built-in template definitions.

The variable name is assigned to o, such as {{_tp_= multiline text}}, resulting in o._tp_=” multiline text “.

2. {{: multi-line code; Returns plain text}}

Execute multiple lines of code immediately and treat the returned content as plain text, escaping HTML if any, such as: {{:var I =”

“; I}} the result is < div> .

Note: if there is a penultimate line of code, the code must end with; . This is not required anywhere else, because parsing the JS code format is a complex business, and ending with a semicolon is much easier.

3. {{:: multiline code; Returns HTML}}

Execute multiple lines of code immediately and return the content as is; This has the same syntax as {{:}}, except that it does not escape the return result and is used to return HTML. {{::var I =”

“; I}} results in

.

{} : simple syntax

This syntax requires the entire code in one line, multiple lines please use the pre-processing syntax.

This syntax can be written in four ways:

1. {fn: single-line code; Return plain text}

Executes a piece of code that returns plain text, escaping HTML if any. Such as {fn: o.n um = 1; } {fn:1+o.num} and {fn:var n=1+o.num; N} is 2 and 2

2. {fn:: single line of code; Returns HTML}

This has the same syntax as {fn:}, except that it does not escape the return result and is used to return HTML.

3. {attributes; Optional single-line code; Return plain text}

Reads the property value of the o object, returns plain text, if any HTML is escaped. For example, {name} takes o.name as the return value and escapes.

Properties can be followed by complex expressions. For example: {num – 100? ‘Yes ‘:’ None ‘} executes the expression o.nam-100? ‘Have ‘:’ nothing’ is returned and escaped.

This syntax is based on the {fn:} syntax, but it automatically prefixes the code with o., simplifying the retrieval of object attributes.

4. {: attribute; Optional single-line code; Returns HTML}

This has the same syntax as {attribute}, except that it does not escape the return result and is used to return HTML.

This syntax is based on the {fn::} syntax, except that it automatically prefixes the code with o., simplifying the retrieval of object attributes.

Methods the document

BuildHTML(tp,obj)

Tp: HTML template string.

Obj: data object.

Return value: HTML result.

BuildHTMLArray(tp,list,check)

Tp: HTML template string.

List: Array of objects.

Check :fn(item,index), check function, item is the current traversal object,index is the index of item in the list, return false to stop traversal.

BuildHTMLArray.index

The index currently traversed.

Full function demo

Js (drop browser console execution) :

Var tp = [' < div TXT = "{TXT}" style = "display: {disable?" none ":" pretend to blank "} "> ', 'the expression text: {TXT}', 'expression HTML: {: TXT}', ' Expression of HTML: {: TXT. Replace (/ div/g, "p")} ', 'function returns plain text: {fn: var d = "plus" + o.h HTML; Date. Now () + d} ', '() function returns the HTML: {fn: : o.h HTML}', 'function + built-in template (nested) : {fn: : BuildHTML (o. _tp_, o)}', 'function + + list of built-in template (the nested loop) :', ' {fn: : BuildHTMLArray (o. _tp_, o. chua hilds)} ', '< / div >', 'definition of built-in template (no return value) : {{_tp_ =', '< div >', '< span > {name} < / span >', '< / div >' , '}} ', 'returns text on code: {{: o.n ame', '+ "< p >"', '}} ', 'execution code returns HTML: {{: : var p = "< p >"; ', 'o.n ame + p', '}} ', 'returns text on code: {{: var c = 0', '; ', 'the for (var I = 0; I < 1000; i++) {if (I % 3) c + +', '; ', '}; ', 'c', '}} instead! Ha ']. Join (' \ n '); BuildHTML (tp, {disable: false, TXT: "content < div >", HTML: '< I > HTML < / I >, name: "little video < I >", childs: [{name: "potatoes < I >"}, {name: "iQIYI"})});Copy the code

The results of

<div txt="Content & # 60; div>" style="Display: Pretend blank">Expression text: content &#60; div&#62; Expression HTML: content<div>Expression HTML: content<p>The function returns plain text :1528680191658 plus &#60; i&#62; html&#60; & # 47; i&#62; The function returns HTML:<i>html</i>Function + built-in template (nested):<div>
		<span>Small video & # 60; i&#62;</span>
	</div>Function + built-in template + list (nested loop):<div>
		<span>Potatoes & # 60; i&#62;</span>
	</div>


	<div>
		<span>iQIYI</span>
	</div>

</div>Define built-in template (no return value): Execute code to return text: small video &#60; i&#62; & # 60; p&#62; Execute code to return HTML: small video<i><p>Executing code returns text :666! haCopy the code

Shrink JS files

BuildHTML is compressed with Uglify to 1K size. If you don’t need to do much with lists, you can remove the list parsing optimization and make it 0.8K.

Eval (x) = eval(x); eval(x) = eval(x); eval(x) = eval(x);

Episode: Optimize history

  1. The earliest version only supports the {} syntax, the {{}} preprocessing syntax is added later, and the oldest version has less than 20 lines of code, but it’s still pretty handy.

  2. The _eval cache is added after the {{}} syntax, and is optimized for lists that repeatedly call the same template. It has been optimized twice:

The template is parsed into a function for the first time and cached for every subsequent call, eliminating parsing. Results: The list performance is greatly improved. The template is used only once to parse the performance degradation details, and the SVN submits records:

BuildHtml was upgraded to compile in functional mode, list build efficiency improved significantly, test: nearly 50 times, single build speed down 3 timesCopy the code

The second time, eval increased the cache. The performance of the list was significantly improved, but it was twice as slow as parsing into functions, but overall it was very strong (the regular expression replacement overhead was not much slower than the function execution overhead).

BuildHtml re-optimized, retrofit onlyevalPartially, but not otherwise, column builds can be twice as slow as functional builds, but up to 20 times faster than primitive builds. Individual builds are about the same as primitive builds, and relatively better than functional builds: primitive 2842.516ms 3365.878msevalCache 124.680ms 3725.948ms functional 60.350ms 8512.252msfor(var i=0; i<10000; i++){ BuildHtml(tp); } console.timeEnd(1); console.time(1);for(var i=0; i<10000; i++){ BuildHtml('<div class="{cls+'+Math.random()+'}">{html+'+Math.random()+'}{fn:FormatDate()+'+Math.random()+'}</div>');
}
console.timeEnd(1);
Copy the code