Simple version (handles only one JSX syntax)

1. Compile JSX syntax to react.CreateElement(…) based on babel-preset-react Structure.

According to the regular parsing in Babel and babel-preset- React plug-ins, the result is shown in the figureCopy the code

2. Execute React. CreateElement (type,props,children) to create an object, which is the virtual DOM.

React.createElement("h1", {
    ref: "ref1".key: "key1".id: "title".className: "title".style: {
        "font-size": "12px"."color": "red"}},"\u54C8\u54C8\u54C8")

// The result of performing large is an object

{
    key: 'key1'.props: {children: "Ha ha ha."
        clasName: "title"
        id: "title"
        style: {color: "red"}},ref: "ref1".type: "h1".__proto__: Object
}
Copy the code

Implement the React. CreateElement (type,props,children) method

Steps:

1. Create an object (with four properties by default: Type/Props/Key/Ref) and return the object to 2. React.createElement(type,props,children

/* * function name: createElement * Parameter: type: props: props: props Return an object, such as the result of the react.createElement () execution above */
createElement(type,props,children){
    let obj = {
        type: null.props: {
            children: ' ',
        }
        key: null.ref: null
    };
   
    / / es6 parsingobj = { ... obj type,// => type:type(parameter)props:{ ... props,// structuring the parameter props
            children    // => children: children}}// Handle key and ref
    if('key' in obj.props){
        obj.key = obj.props.key;
        obj.props.key = undefined
    }
    if('ref' in obj.props){
        obj.ref = obj.props.ref;
        obj.props.ref = undefined
    }
    return obj;
}
Copy the code

Reactdom.render (JSX syntax last generated object, container), based on the render method to dynamically create the generated object as a DOM element, inserted into the specified container.

ReactDOM.render(<div>
    <h1 key="key1" id="title" className="title" style={{"font-size":"12px","color": "red}} ">Ha, ha, ha</h1>
</div>.document.getElementById('root'));
Copy the code

Implementation of the Render method

Container: document.getelementById ('root')), callback: /* * function name: render * parameter: obj: (React. CreateElement result), container: document.getelementById ('root')), callback: The callback function returns: render to the page */
render(obj,container,callback){
    let {type,props} = obj || {};
    // Create a label based on type
    let newElement = document.createElement(type);
       
    /* * setAttribute * Attributes that can be set based on setAttribute can be represented in HTML structures */ 
    
    // Create an attribute on the tag according to props
    for(let attr in props){
        // Only the props private properties need to be handled, not the properties on the prototype
        if(! props.hasOwnProperty(attr))break;
        
        // props[attr] may be undefined, may be null
        if(! props[attr])continue;
        
        let value = props[attr];
        
        // handle attr == 'style
        if(attr === 'style') {if(! value)continue;
            // props['style'] is an object
            for(let stylekey in value){
                // Objects only handle their own private attributes
                if(value.hasOwnProperty(stylekey)){
                    // Press each key-value pair of the object into the label's style
                    newElement['style'][stylekey] = value[stylekey]; }}continue;
        }

        // Handle className(class rendered on the page)
        if(attr === 'className'){
            newElement.setAttribute('class') = value;
        }
        
        // Handle children(simple, we only have text nodes)
        if(attr === 'children') {if(typeof value === 'string') {// Create a text node with createTextNode and press it into the label
                let text = document.createTextNode(value) newElement.appendChild(text); }}}// Press the newly generated label into the container
    container.appendChild(newElement);
}
Copy the code

Handles complex JSX syntax

Based on Babel escape

The createElement method creates the virtual DOM

Methods modified

/* * function name: createElementtypeChildren: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: props: propstype,props,... childrens){ props = props ? props : {};let obj = {
        type: null,
        props: {
            children: ' ', } key: null, ref: null }; // es6 parse obj = {... objtype, / / = >type:type(parameter) Props :{... // If the childrens array has only one item, or an empty array, // if the childrens array has more than one item, the children can be a string (or an empty array), or an array, children: childrens.length<=1? (childrens[0] ||' '): childrens // => children: children(parameter)}} // Handle key and refif('key' in obj.props){
        obj.key = obj.props.key;
        obj.props.key = undefined
    }
    if('ref' in obj.props){
        obj.ref = obj.props.ref;
        obj.props.ref = undefined
    }
    return obj;
}
Copy the code

Render function props[attr]=== children; render function props[attr]=== = children

Render function

render(obj,container,callback){
    let {type,props} = obj || {};
    // Create a label based on type
    let newElement = document.createElement(type);
       
    /* * setAttribute * Attributes that can be set based on setAttribute can be represented in HTML structures */ 
    
    // Create an attribute on the tag according to props
    for(let attr in props){
        // Only the props private properties need to be handled, not the properties on the prototype
        if(! props.hasOwnProperty(attr))break;
        
        // props[attr] may be undefined, may be null
        if(! props[attr])continue;
        
        let value = props[attr];
        
        // handle attr == 'style
        if(attr === 'style') {if(! value)continue;
            // props['style'] is an object
            for(let stylekey in value){
                // Objects only handle their own private attributes
                if(value.hasOwnProperty(stylekey)){
                    // Press each key-value pair of the object into the label's style
                    newElement['style'][stylekey] = value[stylekey]; }}continue;
        }

        // Handle className(class rendered on the page)
        if(attr === 'className'){
            newElement.setAttribute('class') = value;
        }
        
        // Handle children(complex,
            // children
            // It can be a string
            // It can also be an object
            // It can also be an array,
                // Array has strings, also JSX object
            
        if(attr === 'children') {// make array processing unified
            if(! (valueinstanceof Array)) {let value = [value]
            }
            
            // Array of variables
            value.forEach((item,index) = >{
                if(typeof value === 'string') {// Create a text node with createTextNode and press it into the label
                    // Create the current item image
                    let text = document.createTextNode(item)
                    newElement.appendChild(text);
                }else{
                    // is a JSX object, re-execute render method
                    // item is a JSX object
                    // newElement is the containerrender(item,newElement); }}}})// Press the newly generated label into the container
    container.appendChild(newElement);
}
Copy the code

Conclusion:

1. Based on Babel and babel-preset-react escape 2. Create a virtual DOM based on React. CreateElement Generate the tag tree from the virtual DOM.Copy the code

Details, a little omission, if there is insufficient or wrong place, welcome the boss to criticize and correct. thank you