Preparation stage
Create a project
- through
create-react-app easy_react
Scaffolding creates a project - Clean up the
src
The catalog, we only have one hereindex.js
Can be - Modify the
index.js
The following
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
const style = {
color: 'red'.background: 'yellow'.fontSize:'20px'
}
ReactDOM.render(
<h1 id={'gu_yan'} className={'gu-yan'} style={style}>
Guyan
</h1>.document.getElementById('root'));
Copy the code
Start the project
- perform
yarn start
The page looks like this
The analysis phase
- will
index.js
Code copy tobabel
, the effect is as follows
- Analysis of the above
- Comparing the code before and after, we see the following changes
/** *
* Guyan *
, document.getElementById('root')); * /CreateElement ()"h1", { id: 'gu_yan'.className: 'gu-yan'.style: style }, "Guyan") Copy the code - will
index.js
The file is modified as follows. The page is found unchanged. The console prints the result as shown in the following figure
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
const style = {
color: 'red'.background: 'yellow'.fontSize: '20px'
};
const element = React.createElement("h1", {
id: 'gu_yan'.className: 'gu-yan'.style: style
}, "Guyan")
console.log(element)
ReactDOM.render(element, document.getElementById('root'));
Copy the code
- As shown in the figure above
React.createElement()
The result of the execution is an object, which we call virtualDOM
Here we can sum up the virtualDOM
The origin of the- 【 1 】 in
webpack
It’s called when you packbabel-loader
That will beJSX
The syntax escape isReact.createElement(...)
In the form of - 【 2 】
React.createElement
The execution returns an object, which is virtualDOM
- 【 1 】 in
- parsing
React.createElement
The execution process of- [1] Collect attribute objects and handle special attributes such as
children
.key
.ref
; This article only illustrates exampleschildren
- [1-1] Create one
props
object - [1-2] hang each attribute in the second parameter object passed in
props
Is the value of the second argument object relative to - [1-3]
props
Hang achildren
Property, and the value is the third parameter passed in- Note:
children
The value is either a string or an array. If you executeReact.createElement
When the parameter passed is greater than 3, thenchildren
The value of is an array of all attributes except the first two
- Note:
- [1-1] Create one
- [2] will be incoming
type
And the collected property object is passed in as a parameterReactElement
To execute (reactElement(type,props)
) - [3]
ReactElement
Execute to create anewElement
object - [4]
newElement
Hang a? typeof
Property, here we uniformly assign its value toSymbol(react.element)
- [5]
newElement
Hang atype
Property with the value passed intype
- [6]
newElement
Hang aprops
Property with the value passed inprops
- [7] Return
newElement
(virtualDOM
)
- [1] Collect attribute objects and handle special attributes such as
- parsing
ReactDom.render
The execution process of- [1] Judge the incoming virtual
DOM
The type of- [1.1] Plain text type, the first parameter may be
string
ornumber
, a real text node is created directly - [1.2] Ordinary
html
Tag components, such as<div></div>
Of the first argument objecttype
A property is astring
Type to create a real oneDOM
Node and take the first parameterprops
Some common properties in the property are mounted to the realDOM
Node, and for some special properties likechildren
For details, see belowThe implementation phase - [1.3] Function components (
function Component
) of the first argument objecttype
A property is afunction
Type,type
Executes the object passed the first argumentprops
- [1.4] Class Components (
class Component
) of the first argument objecttype
There’s one on the propertyisReactComponent
Properties,new type(props)
Create an instance and let the instance’srender
Methods to perform
- [1.1] Plain text type, the first parameter may be
- [2] Insert the created real node into the parent node
- [1] Judge the incoming virtual
The implementation phase
react.js
// _react.js
class Component {
static isReactComponent = true;
constructor(props){
this.props = props; }}function ReactElement(type,props){
const virtual_dom = {};
virtual_dom.?typeof = Symbol.for('react.element');
virtual_dom.type = type;
virtual_dom.props = props;
return virtual_dom;
}
function createElement(type,config,children){
const props = {};
for (const propName in config){
if(config.hasOwnProperty(propName)){ props[propName] = config[propName]; }}const childrenLength = arguments.length - 2;
if (childrenLength === 1){
props.children = children;
}else if (childrenLength > 2){
props.children = Array.from(arguments).slice(2);
}
return ReactElement(type,props);
}
export default {createElement,Component}
Copy the code
react-dom.js
// _react_dom.js
function render(virtual_dom,parent_node){
if (typeof virtual_dom ==='string' || typeof virtual_dom === 'number') {/** * handles direct rendering of text nodes, such as reactdom.render ('guYan', document.getelementByid ('root')); * /
return parent_node.appendChild(document.createTextNode(virtual_dom));
}
if (virtual_dom.type.isReactComponent){
/**
*处理直接渲染Class Component的情况
*/
virtual_dom = new virtual_dom.type(virtual_dom.props).render();
render(virtual_dom,parent_node);
}
if (typeof virtual_dom.type === 'function') {/**
*处理直接渲染function Component的情况
*/
virtual_dom = virtual_dom.type(virtual_dom.props);
render(virtual_dom,parent_node);
}
let {type , props} = virtual_dom;
let real_dom = document.createElement(type); // Create a real node based on type
for (const propName in props){ // handle the props
if(props.hasOwnProperty(propName)){
const prop = props[propName];
if(propName === 'className'){
real_dom.className = prop;
}else if (propName === 'style') {let cssText = Object.keys(prop).map(attr= >(`${attr.replace(/([A-Z])/g.function() {return ` -The ${arguments[1].toLowerCase()}`
})} :${prop[attr]}`)).join('; ');
real_dom.style.cssText = cssText;
}else if (propName === 'children') {/** *children may be a string or an array, if it is a string converted to an array, and then recursively calls render, note that the parent node passed in is real_dom */ that we created
let childArr = Array.isArray(prop) ? prop : [prop];
childArr.forEach(child= >render(child,real_dom));
}else{ real_dom.setAttribute(propName,prop); }}}return parent_node.appendChild(real_dom);
}
Copy the code
Write in the last
- Everyday use of functional components is recommended
- 1. Easy to use
- 2. Save memory
- 3. Improve performance
- In this paper, the principle is explained only at the surface level. Without in-depth analysis, how to error also hope to teach. Thank you very much!