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