1.1. Virtual DOM
FAQ: What is react virtual dom? Tell me about the diff algorithm?
When you get a question, what is the general answer? Why? How to do? Then go with this idea!
what
Use JavaScript objects to represent DOM information and structure, and when the state changes, re-render this JavaScript object structure. This JavaScript object is called virtual dom;
why
DOM operations are very slow, and slight operations may cause page re-layout, which is very performance-intensive. Compared to DOM objects, js objects are faster and simpler to process. By comparing the difference between the old and new vdom s through the diff algorithm, dom operations can be performed in batches and minimized, thereby improving performance.
where
Views are described in JSX syntax in React, and after they are translated by babel-loader, they become in the form of React.createElement(...), which will generate vdom to describe the real dom. If the state changes in the future, vdom will make corresponding changes, and then compare the difference between the new and old vdom through the diff algorithm to make the final dom operation.
Speaking of JSX here, let’s talk about it by the way:
What is JSX
syntactic sugar, React use JSX to replace the conventional JavaScript. JSX is a look like XML of JavaScript Syntax expansion.
React practical video explanation: into learning
Why do you need JSX
Development efficiency: use JSX Writing templates is easy and fast. effectiveness: JSX compiles to JavaScript Code-post optimizations are made to execute faster. Type Safety: Errors can be found during compilation.
React 16 Principles
babel-loader will be precompiled JSX for React.createElement(...)
React 17 Principles
React 17 middle JSX conversion will not JSX convert to React.createElement,but automatically from React of package Introduce a new entry function in and call it. In addition, this upgrade will not change JSX grammar, old JSX Conversions will also continue to work.
Similarities and differences with vue
The design of virtual dom+jsx in react was there from the beginning, and vue only appeared in the evolution process, and appeared after version 2.0.
jsx is originally a js extension, and the escaping process is much simpler and more direct; the process of compiling template into render function by vue requires a complex compiler to convert the string-ast-js function string
1.2, render, Component basic core api
render
ReactDOM.render(element, container[, callback]);
When called for the first time, all DOM elements in the container node will be replaced, and subsequent calls will use React's DOM diffing algorithm for efficient updates.
If an optional callback function is provided, the callback will be executed after the component is rendered or updated.
Node type
1,text node 2,html label node 3,functional component 4,class component ...
functional component
// start with bigger letters function Welcome(props) { return <h1>Hello, {props.name}</h1> }
class component
React components can be defined in the form of classes or functions. To define class components, you need to inherit React.Component or React.PureComponent:
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1> } }
1.3, handwritten short version of myreact
Implement initial rendering of native label nodes, text nodes, function components and class components
First create a React project with Create React App, install dependencies and run;
Then add this code to src/index.js to check the version number and make sure you have version 17
console.log("version", React.version);
It is precisely because in React17 that React will automatically replace JSX with js objects, so we mainly need to comment out src/index.js:
// import React from "react"; // import ReactDOM from "react-dom";
Then create a myreact folder under src and create a react-dome.js inside
// vnode virtual dom object // node real dom node // ! First render function render(vnode, container) { // react17 can automatically turn virtual dom console.log("vnode", vnode); // vnode->node const node = createNode(vnode); // node->container container.appendChild(node); } // create node function createNode(vnode) { let node; const {type} = vnode; // todo creates different node nodes according to the component type if (typeof type === "string") { // native label node node = updateHostComponent(vnode); } else if (typeof type == "function") { // Functional components Let’s distinguish between class components and functional components again node = type.prototype.isReactComponent ? updateClassComponent(vnode) : updateFunctionComponent(vnode); } else { // text node node = updateTextComponent(vnode); } return node; } // native label node function updateHostComponent(vnode) { const {type, props} = vnode; const node = document.createElement(type); console.log('document.createElement', node) // update node section updateNode(node, props); // Attributes reconcileChildren(node, props.children); // traverse children return node; } // update properties function updateNode(node, nextVal) { Object.keys(nextVal) .filter((k) => k !== "children") // filter children .forEach((k) => (node[k] = nextVal[k])); // Generate properties } // text node function updateTextComponent(vnode) { const node = document.createTextNode(vnode); return node; } // functional component function updateFunctionComponent(vnode) { const {type, props} = vnode; // type is a function const vvnode = type(props); // vvnode->node const node = createNode(vvnode); return node; } // class component function updateClassComponent(vnode) { const {type, props} = vnode; // Class components require new const instance = new type(props); console.log('instance', instance); const vvnode = instance.render(); console.log('vvnode', vvnode); // vvnode->node const node = createNode(vvnode); return node; } // traverse children function reconcileChildren(parentNode, children) { // It is a little different from the source code, but it is also to determine whether it is an array const newChildren = Array.isArray(children) ? children : [children]; for (let i = 0; i < newChildren.length; i++) { let child = newChildren[i]; // vnode // vnode->node, node is inserted into parentNode render(child, parentNode); } } export default { render };
Next, create a src/myreact/Component.js file:
// Class components must inherit from Component or PureComponent function Component(props) { // Need to bind this this.props = props; } // Made a markup of a class component Component.prototype.isReactComponent = {}; export default Component;
Oh, don't forget to change the contents of the src/index.js file:
// import React from 'react'; // import ReactDOM from 'react-dom'; import ReactDOM from './myreact/react-dom'; import Component from "./myreact/Component"; import './index.css'; // import App from './App'; import reportWebVitals from './reportWebVitals'; class ClassComponent extends Component { render() { return ( <div> <p>class component-{this.props.name}</p> </div> ); } } export default ClassComponent; function FunctionComponent(props) { return ( <div> <p>functional component-{props.name}</p> </div> ); } const jsx = ( <div className="myjsx"> <h1>111111</h1> <h2>222222</h2> <h3>111111</h3> <a href="https://www.baidu.com/">Baidu</a> <FunctionComponent name="I am a functional component" /> <ClassComponent name="I am a class component" /> </div> ) // native tags // text node // functional component // class component ReactDOM.render( jsx, document.getElementById('root') ); // console.log("version", React.version); // version 17.0.1 // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
The overall code is like this, the specific process will not be explained in detail here, you can take a good look at the code, and you can contact me if you have any questions.
summary
1,React17 middle, React will automatically replace JSX for js object. 2,js object i.e. vdom,it can fully describe dom structure. 3,ReactDOM.render(vdom, container)can vdom convert to dom and append to container middle. 4,In fact, the conversion process needs to go through a diff process.