Simple implementation _javascript techniques for Javascript string templates

Source: Internet
Author: User

This is a problem that came about two years ago when I was doing the first real site in my life.

The site uses a back-and-forth separation method that returns JSON data from the REST of the backend and renders the front-end to the page.

Like many beginner Javascript novices, I used to embed the JSON data in HTML in the form of a concatenation string. There is less code at the start and is acceptable for the time being. But when the page structure is complex, its weaknesses begin to become unbearable:

    1. The writing is incoherent. Each write a variable will be broken, insert a + and. It's very easy to make mistakes.
    2. cannot be reused. HTML fragments are discrete data and it is difficult to extract the parts that are duplicated.
    3. The <template> tag is not well utilized. This is a new tab in HTML5, and it is highly recommended that you put HTML templates into <template> tags to make your code simpler.
    4. That's how I felt at the time:

Is this the hell you're kidding me?

To solve this problem, I temporarily put down the project on hand and spent half an hour implementing a very simple string template.

Requirements Description

Implement a render (template, context) method that fills the placeholders in template Requirements:

There is no need to have control flow components (such as loops, conditions, etc.), as long as there is a variable substitution function
Cascading variables can also be expanded
The escaped delimiter {and} should not be rendered, and the delimiter is allowed to have white space characters between the variables
Example:

Render (' My name was {name} ', {
  name: ' Hsfzxjy '
});//My name is Hsfzxjy

render (' I am in {profile.location} ', {
  name: ' Hsfzxjy ', profile
  : {
    location: ' Guangzhou '
  }
}]//I AM in Guangzhou

render (' { Greeting}. \\{this block won't be rendered} ', {
  greeting: ' Hi '
});//Hi. {This block won't be rendered}

Realize

First write down the frame of the function:

function render (template, context) {

}

Obviously, the first thing to do is to match the placeholder in the template.

Matching placeholders

The matching thing must be given to the regular expression to complete. So what should this regular expression look like?

According to the description of Requirement 1 and 2, we can write:

var reg =/\{([^\{\}]+) \}/g;

As for Demand 3, I first thought of the concept of forward matching, unfortunately Javascript does not support, but to use a compromise approach:

var reg =/(\) \{([^\{\}\\]+) (\) \}/g;
If the first or third grouping value is not empty, it is not rendered
now, the code should be:

function render (template, context) {

  var tokenreg =/(\)? \{([^\{\}\\ ]+) (\) \}/g;

  Return Template.replace (Tokenreg, function (Word, SLASH1, token, slash2) {
    if (Slash1 | | slash2) {//Match to escape character
      Retu RN word.replace (' \ \ ', '); If the delimiter is escaped, do not render
    }

    //...
  }
}

Placeholder Replacement

Well, the regular expression is OK, and the next thing to do is to replace the job.

According to demand 2, the template engine should not only be able to render first-level variables, but also to render multilevel variables. How do you do that?

Actually very simple: will token press. Separated, the step-by-look can be:

var variables = token.replace (/\s/g, '). Split ('. '); Cutting token
var currentobject = context;
var i, length, variable;

Step
-by-step lookup context for (i = 0, length = variables.length, variable = variables[i]; i < length; ++i)
  Currentobjec t = currentobject[variable];

return currentobject;

However, it is possible that the specified variable does not exist, and the code above token the error. For a better experience, the code is better able to have fault tolerance:

var variables = token.replace (/\s/g, '). Split ('. '); Cutting token
var currentobject = context;
var i, length, variable;

for (i = 0, length = variables.length, variable = variables[i]; i < length; ++i) {
  Currentobject = Currentobject[va Riable];
  if (Currentobject = = Undefined | | | currentobject = = NULL) return '; If the object of the current index does not exist, the empty string is returned directly.
}

return currentobject;

By combining all the code together, you get the final version:

function render (template, context) {

  var tokenreg =/(\)? \{([^\{\}\\]+) (\)? \}/g;

  Return Template.replace (Tokenreg, function (Word, SLASH1, token, slash2) {
    if (Slash1 | | slash2) {return 
      Word.rep Lace (' \ \ ', ');
    }

    var variables = token.replace (/\s/g, '). Split ('. ');
    var currentobject = context;
    var i, length, variable;

    for (i = 0, length = variables.length, variable = variables[i]; i < length; ++i) {
      Currentobject = Currentobject[v Ariable];
      if (Currentobject = = Undefined | | | currentobject = = NULL) return ';
    }

    return Currentobject
  })
}

Remove the blank line, altogether 17 lines.

To hook a function to a prototype chain of String

Even, we can make some cool effects by modifying the prototype chain:

String.prototype.render = function (context) {return
  render;

After that, we can call it this way:

"{greeting}! My name is {author.name}. ". Render ({
  greeting: "Hi",
  Author: {
    name: "Hsfzxjy"
  }
});
Hi! The My name is Hsfzxjy.

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.