preface
Some nonsense and personal perception, see dry goods directly skip…. To the JSX
I’ve been writing on and off for half a year now. It’s basically a stack of personal skills and answers to interview questions. Interested partners can click on my home page to see.
Talk about today’s main character -React. The React source code is something I’ve always wanted to read and read, but I often feel sleepy. Then I started to get lazy and started reading around things like react-Router, react-redux, etc. I used to write articles after I read them. Now I want to read it while I write it, so let’s look at it another way. If there is something wrong, welcome to discuss, if you think it is ok, you can click a like, thank you!
As a heavy user and fan of React. I will be with you from “user” to “understanding” progress!
React information
Utilitarian perspective
Open recruitment software, now basically large factories, and even outsourcing companies are generally required to know React or Vue. The salary is also very attractive.
(Picture is from Boss.)
In order to make a fortune this simple dream should also study.
Perspective of Learning
Angular, React, and Vue dominate the front end. React and Vue are preferred in China. Therefore, learn React from the perspective of learning.
www.npmtrends.com/react-vs-vu…
Why learn source code
I’ve asked this question before. Almost all interviews are about building rockets and turning the screws.
I think there are two ways to look at it:
- The applicant
- Read and
React
In the case of solving the problem, the ceiling must be raised - An excellent framework is an excellent teacher
- Read and
- Employer, since everyone can do the job, I’ll find someone who knows more about it
JSX
Without further ado, let’s get to it.
React JSX JSX JSX JSX JSX JSX JSX JSX JSX I’ll give you a demo to help you answer it.
import React from "react"; import ReactDOM from "react-dom"; Class App extends React.Component {render() {const text = "ha ha" return (<div> <p>{text}</p> </div>); } } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);Copy the code
Let me ask you a few questions first. If you can answer them clearly and quickly, congratulations, you have a solid foundation. If not, take a look together, and then you can write your answers in the comments section for discussion.
- What is the
JSX
?JSX
andJS
What does it matter? JSX
What is the underlying principle of?- why
React
Want to chooseJSX
?
Take the question with you.
What is the JSX
Here’s a quote from React.
const element = <h1>Hello, world! </h1>;Copy the code
It’s called JSX, and it’s a syntax extension to JavaScript.
Syntactic extensions, which means that JS has everything it has, and some other functionality. Obviously, I haven’t seen him in JavaScript learning. Can it run in JavaScript? Open the Chrome Console.
The syntax errors are all over the place. It seems that this part is an extra function. How does that work?
{
test: /\.(js|jsx)? $/.// Enable caching
options: { cacheDirectory: true },
loader: 'babel-loader',},Copy the code
It tells WebPack that we need to use Babel to parse JSX code. Ok, that is, to run JSX, you must parse with Babel. Okay, what is Babel?
babel
Play a quote from Babel’s website
Babel is a JavaScript compiler
Babel is a toolchain for converting ECMAScript 2015+ version code into backwardly compatible JavaScript syntax so it can run in current and older versions of browsers or other environments.
Babel, in fact, helps us parse the code that we write and make it look like a browser. JSX, for example, and fresh ES6 syntax can run on older browsers and be understood by older browsers.
Which begs the question, what has Babel turned JSX into?
Online conversion: babeljs. IO /repl
You can throw that little demo up there.
No. The thing we return out becomes react.createElement. Lol, that’s why we didn’t even use React. JSX will eventually be converted to react. createElement, which will be used! The latest one, however, does not need to be quoted and will not report any errors, as it identifies itself.
Website: zh-hans.reactjs.org/blog/2020/0…
// Imported by the compiler (forbid self-imported!) import {jsx as _jsx} from 'react/jsx-runtime'; function App() { return _jsx('h1', { children: 'Hello world' }); }Copy the code
Note that the source code does not need to introduce React to use JSX! (You still need to introduce React, though, in order to use the hooks or other exports that React provides.)
Let’s go back to what we mentioned earlier on React
It’s called JSX, and it’s a syntax extension to JavaScript.
React.createElement () {react. createElement () {react. createElement ();
createElement
React (JSX); react (JSX); react (JSX);
export function createElement(type, config, children) {
// The propName variable is used to store element attributes that need to be used later
let propName;
// props is the set of key-value pairs used to store element attributes
const props = {};
// Key, ref, self, source are all attributes of the React element
let key = null;
let ref = null;
let self = null;
let source = null;
The config object stores the attributes of the element
if(config ! =null) {
// The first thing you do is assign the ref, key, self, and source attributes in order
if (hasValidRef(config)) {
ref = config.ref;
}
// String the key here
if (hasValidKey(config)) {
key = ' ' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// Move all the properties in config to props one by one
for (propName in config) {
if (
// Filter out properties that can be pushed into the props objecthasOwnProperty.call(config, propName) && ! RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; }}}// childrenLength is the number of children of the current element; the 2 subtracted is the length of the type and config parameters
const childrenLength = arguments.length - 2;
// If type and config are omitted, there is only one argument left, which generally means that the text node is present
if (childrenLength === 1) {
// assign this parameter directly to props. Children
props.children = children;
// Handle nested child elements
} else if (childrenLength > 1) {
// Declare an array of children
const childArray = Array(childrenLength);
// Push the child element into the array
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
// Finally, assign this array to props. Children
props.children = childArray;
}
/ / defaultProps processing
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) { props[propName] = defaultProps[propName]; }}}// Finally returns a call to ReactElement execution method, passing in the arguments just processed
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
Copy the code
Instead of looking at the parameters, let’s look at the name of the return value and the name of the function. Our initial guess is that JSX creates a React element using createElement, which is then rendered to the element we named by reactdom.render.
Ok, so the JSX elements we normally write are the ones generated by ReactElement. Let’s see what ReactElement generates.
Let’s print out JSX that we usually write.
Intuitively, does it feel like this is a virtual DOM node, and it has a type and then a DIV, and the corresponding div tag is an HTML div tag? And then there’s className, which obviously corresponds to the class. Let’s go and have a look.
ReactElement
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This is the React node identifier
$$typeof: REACT_ELEMENT_TYPE,
// This is clearly the corresponding HTML tag
type: type,
key: key,
ref: ref,
props: props,
// Who created the record? Dig a hole
_owner: owner,
};
// The configuration of the development environment, mainly Object. Freeze, can be found in the MDN. I don't want to go into that
if (__DEV__) {
// The validation flag is currently mutative. We put it on
// an external backing store so that we can freeze the whole object.
// This can be replaced with a WeakMap once they are implemented in
// commonly used development environments.
element._store = {};
// To make comparing ReactElements easier for testing purposes, we make
// the validation flag non-enumerable (where possible, which should
// include every environment we run tests in), so the test framework
// ignores it.
Object.defineProperty(element._store, 'validated', {
configurable: false.enumerable: false.writable: true.value: false});// self and source are DEV only properties.
Object.defineProperty(element, '_self', {
configurable: false.enumerable: false.writable: false.value: self,
});
// Two elements created in two different places should be considered
// equal for testing purposes and therefore we hide it from enumeration.
Object.defineProperty(element, '_source', {
configurable: false.enumerable: false.writable: false.value: source,
});
if (Object.freeze) {
Object.freeze(element.props);
Object.freeze(element); }}return element;
};
Copy the code
$$typeof is the React node. Then there are the normal parameters, such as key, ref, props, and so on.
ReactDOM.render
This is how the React node renders as a real node. No more words, on the source code!
export function isValidContainer(node: mixed) :boolean {
return!!!!! ( node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || (node.nodeType === COMMENT_NODE && (node: any).nodeValue ===' react-mount-point-unstable '))); }export function render(
element: React$Element<any>,
container: Container,
callback: ?Function.) {
// The container can be found
invariant(
isValidContainer(container),
'Target container is not a DOM element.',);if (__DEV__) {
const isModernRoot =
isContainerMarkedAsRoot(container) &&
container._reactRootContainer === undefined;
if (isModernRoot) {
console.error(
'You are calling ReactDOM.render() on a container that was previously ' +
'passed to ReactDOM.createRoot(). This is not supported. ' +
'Did you mean to call root.render(element)? ',); }}// There is something about fiber architecture that I want to talk about later
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
}
Copy the code
Does it feel easy to remove the __DEV__ case? Return the result of a function…
ReactDOM.hydrate
This function I find interesting is only one line different from reactdom.render
legacyRenderSubtreeIntoContainer(
null,
element,
container,
- false,
+ true,
callback,
);
Copy the code
First, this hydrate means water hydrate. Add water and color to a knot. It was used to add click events and so on in SSR process. ReactDOM.Render will be phased out after React17 and replaced entirely with ReactDOM. Hydrate
React
The reactdom.render () method of manipulating server render containers for hydrate is deprecated and will be removed in React 17. Instead, use hydrate().
Why use JSX
So here’s a little tip for solving this problem. Why to XX is actually to ask you, the benefits of XX. Ok, that’s an easy answer
First, because without JSX, we would have hundreds of React. Crearteelements in our code.
Second, this syntactic sugar allows developers to create virtual DOM using familiar HTML tags, reducing learning costs. Improve development efficiency and experience
The rest of the pit
- LegacyRenderSubtreeIntoContainer (relating to the fiber structure
- _owner (What does this property do when it is created
Everyone like, trouble like ah!! Any questions can also be pointed out in the comments section
The index
zh-hans.reactjs.org/docs
www.babeljs.cn/docs/