preface

  • The structure of the article uses [point out the stage goal, and then to solve the problem as the entrance, to solve the idea as a means] to achieve the goal of this article, if you have a little inspiration, do not waste this effort ^-^
  • Article ideas article and implement article 】 【 】, is thinking, this paper suggested see two Windows synchronous read – “the Vue implemented – ast | | the first edition piece render function

The target

The first stage: template writing compatibility

Look at the use of

There are three ways to write HTML templates in Vue

Default execution of render logic: priority 1. Find el property 2. First find render method 3. Then find the template

# HTML <div id="app">
        <div style="color:yellow">Name {{name}}</div> <span>111</span>
</div>

 let vm = new Vue({
            el: '#app'.data(){
                return {
                  name: 'Wang Zhiyuan'.age: 23}}})/ / or $mount
 // This method is for whether or not to pass the EL attribute that can achieve control of vUE mount timing
  let vm = new Vue({
            data(){
                return {
                  name: 'Wang Zhiyuan'.age: 23
                }
            }
 })
 vm.$mount('#app')


# template ==================================
 let vm = new Vue({
            el: '#app'.data(){
                return {
                  name: 'Wang Zhiyuan'.age: 23}},template: ` < div id = "app" > < div > name {{name}} < / div > < span > 111 < / span > < / div > `
 })
 # render ==================================
 let vm = new Vue({
            el: '#app'.data(){
                return {
                  name: 'Wang Zhiyuan'.age: 23}},render(_c){
               return _c('div', {id: 'app'
                },[_c('div', {},Name of `The ${this.name}`),_c('span', {},'111')]}})Copy the code
The core problem
  • How are the three ways compatible
solution

The compatibility problem is written differently but for the same purpose, namely generating ast trees from HTML strings, which is the function of render, which means that our focus is on converting all template scripts to render functions (note the priority).

  • First judge whether the user has defined render, if defined directly use this function
  • If no template is defined, the system checks whether there is a template. If there is no template, the system obtains an HTML string according to EL and assigns a value to template. The render function is generated according to template

Stage 2: Implement the render function

Look at the use of
return _c('div',[_c('div', {style: 'color:yellow'},Name of `The ${this.name}`),_c('span', {},'111')])
Copy the code

= >

<div><div style="color: yellow;">His name is Wang Zhiyuan</div><span>111</span></div>
Copy the code
The core problem
  • Implement _c function == function is to transfer user information into vDOM, that is, virtual node
  • Implement the _update method == function to render the page via vDOM
solution
  • Define the VDOM structure{tag,data,key,children,text }And the function _c that creates the VDOM from the information
  • Pass _c to render and get the render function return value, which is a VDOM
  • Render pages with VDOM using deep traversal + DOM processing
    • Generate the corresponding HTML structure through VNode, and pay attention to handling attributes
    • Find the mount point via EL and replace it
Here is the domdiff core of vue. Patch is performed here, that is, new and old virtual nodes are compared and then mounted. Due to space problem, only the first rendering is implemented here, that is, real DOM logic is rendered according to Vnode, and a separate article is written laterCopy the code
Problem to solve: Convert HTML to render function
1. Use the AST syntax tree to describe HTML, so that JS can handle it. Generating the render function with the AST does this by turning different issues into handled issues

Stage 3: Get information through template

The core problem
  • How do I get the HTML information in the template string
solution
  • The re extracts valid information, then intercepts the original HTML string and continues the loop until the HTML is empty

    • Handling start tags<div id="11">
      • Processing label name
      • Processing properties
    • Handling closing tags
    • Handling text

The fourth stage: process and obtain information and generate AST tree

Look at the use of
User-written code
<div id="app">
        11
        <div style="color:yellow">Name {{name}}</div>
    </div>
Copy the code
We need the structure of transformation
{
    parent: null
    tag: "div"
    type: 1.attrs:[
       {name: "id".value: "app"}].children: [{
        text: "11"
		type: 3}, {tag: 'span'.parent: parent div,attrs: [{name: "style".value: {color: "yellow"}}].children: [{
           type: 3.text: "Name {{name}}"}}}]]Copy the code
The core problem
  • What data structure is used to describe the information obtained?
  • How to verify that the HTML structure is correct (i.e<div></span></div>This closure error case), that is, build the parent-child structure
solution
  • Note that this scenario fits well with a data structure — a tree — that diverges from a root node and has the same subscale (leaf structure); We can use a tree structure to describe the acquired information, that is, generate an AST tree according to the template
    • Define tree cell structure: tag correspondence{tag: tagName, // tag type: 1, // tag type: 1, // children:[], // attrs, // attribute set parent:null // parent element}; Text corresponding{type:3,text:text}
    • Generate corresponding tree units according to the obtained information
  • Using the stack structure record processing label process, the label information object is pushed into the stack when processing the start label, and when processing the close label
    • First, the stack is pushed and the label’s parent information object is recorded (the parent attribute of the pushed element points to the top element).
    • Secondly, the off-stack element is stored in the children attribute of the top element of the stack to build the parent-child structure
    • Finally, at the end of the processing, check whether the stack is empty. If it is not empty, it indicates that the match is abnormal

Stage 5: Generate the render function according to the AST, and return the corresponding VNode when the function is executed

Look at the use of
/ / ast structure
{
    parent: null
    tag: "div"
    type: 1.attrs:[
       {name: "id".value: "app"}].children: [{
        text: "11"
		type: 3}, {tag: 'span'.parent: parent div,attrs: [{name: "style".value: {color: "yellow"}}].children: [{
           type: 3.text: "Name {{name}}"}}}]]// Need to be converted to
render(){
   return _c('div', {id:'app'},_v('11'),_c('span', {style:"color:yellow"},"Name"+_s(name)))
}
Copy the code

Where, _v is used to generate the text virtual node _c is used to generate the label node _S is used to convert the object into a string to avoid errors when the string is converted to a function

The core problem
  • How does the AST tree structure transform functions?
  • Internal variables should be evaluated on the VM. How?
solution
  • The AST can convert strings through deep traversal and then string concatenation, and then string to Function through new Function
  • With allows you to specify global variables within a function
/ / with examples
let obj = {
    a: 1
}
with(obj){
     console.log(a);
}
Copy the code
The last

Mount render before the user delivers it and reuse the patch logic

At this point, the AST is complete.

Concrete implementation link

Vue implemented – ast | | the first edition piece render function Vue – ast article second edition | | realizing ast/vnode and page rendering