This is the 18th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

In the rendering process of Vue, if the user does not pass the render function, it needs to generate the render function by compiling the DOM structure of template or EL. Generating the render function is a complicated and important thing, which mainly does is to compile the template into AST. Generate the virtual DOM based on the AST operation, and finally return the required render function

Get the core flow to compileToFunction

export function compileToFunction(template) {
  // 1. Parse HTML to generate AST
  const ast = parseHTML(template);
  // optimize(ast, options)

  // 2. Generate render function according to AST
  const { render } = generator(ast);

  // render returns the virtual DOM
  return {
    ast,
    render,
  };
}
Copy the code

As you can see, converting a template into a Render function is not as complicated as you might think, so we continue with the core flow

The first step is to compile the HTML to generate an AST. In Vue, the AST is generated through the regular match parsing template. Before starting the parseHTML function, it is necessary to understand some of the regular expressions used in it

Parsing HTML elements

The most common regees for matching parsing HTML are tags that can be parsed. Tags of HTML elements appear in pairs: start tags and end tags (closed tags), as well as single tags such as IMG that do not have an end tag. Components must exist in VUE, so the way components are written also needs to match

Matches HTML elements, such as div and SPAN, and custom components, such as el-button and el-input-number

const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3 001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}] * `;
Copy the code

Matching a namespace tag, such as

will match div:name

const qnameCapture = ` ((? :${ncname}\ \ :)?${ncname}) `; // <asd:asd>
Copy the code

With the re above, you can happily match the opening and closing tags

const startTagOpen = new RegExp(` ^ <${qnameCapture}`); // The re at the beginning of the tag captures the tag name
const startTagClose = /^\s*(\/?) >/; // Match tag end >
const endTag = new RegExp(` ^ < \ \ /${qnameCapture}[^ >] * > `); // Match  at the end of the tag
Copy the code

attribute

Used to configure attributes on HTML tags

const attribute = /^\s*([^\s"'<>\/=]+)(? :\s*(=)\s*(? :"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))? /; 
Copy the code

Used to match the current presence of attributes and extract key values

const temp = `class="btn-blue"`;
const attr = temp.match(attribute);
Copy the code

If attr has a value, it indicates the presence of the attribute, which can then be fetched

const name = attr[1]; // class
const value = attr[3] || attr[4] || attr[5]; // btn-blue
Copy the code

annotation

Comments are often added to code (although many people don’t write comments in HTML), and they need to be matched

const comment = / ^ 
      ;
const conditionalComment = / ^ 
      ;
Copy the code

These are the regular expressions needed to parse HTML to generate an AST