Deeply understand the update of state and props in react

Zhang Yue 2021-02-23 01:16:28
deeply understand update state props


Preface

In this article we'll see React How to deal with it state Update . And how to build it effects list. We will introduce in detail render( Rendering ) Stage and commit( Submit ) What happened at that stage .

We will be in completeWork Function React how :

  1. to update state attribute .
  2. call render Method and compare child nodes .
  3. to update React Elemental props.

And in commitRoot Function React how :

  1. Update element textContent attribute .
  2. call componentDidUpdate Life cycle approach .

But before that , Let's first look at calling setState when React How to arrange work . Let's use an example from the previous article , Easy to explain , A simple counter component :

1.gif

class ClickCounter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((state) => {
return {count: state.count + 1};
});
}
componentDidUpdate() {}
render() {
return [
<button key="1" onClick={this.handleClick}>Update counter</button>,
<span key="2">{this.state.count}</span>
]
}
}

Schedule updates

When we click the button ,click Event is triggered ,React Will perform our callback . In our application , He will update us state.

class ClickCounter extends React.Component {
...
handleClick() {
this.setState((state) => {
return {count: state.count + 1};
});
}
} 

every last React Components , There's a connection updater( Updater ).updater Acts as a component and React core The bridge between . This allows setState stay ReactDOM,React Native, Server side rendering and test cases are implemented in different ways .

ad locum , We will focus on ReactDOM in updater( Updater ) The implementation of the . It has been used. Fiber reconciler. about ClickCounter Components , It is classComponentUpdater. It is responsible for searching Fiber example , Queued updates , Scheduling work .

When updating , The Updater will be in Fiber Add update queue on node . In our case ,ClickCounter Component corresponding Fiber The structure of the node is as follows :

{
stateNode: new ClickCounter, // Keep right class References to component instances
type: ClickCounter, // type Property points to constructor
updateQueue: { // state Update and callback ,DOM Updated queue .
baseState: {count: 0}
firstUpdate: {
next: {
payload: (state) => { return {count: state.count + 1} }
}
},
...
},
...
}

As you can see updateQueue.firstUpdate.next.payload The content is that we are setState Callbacks passed in . It means in render The first update that needs to be processed in phase .

Handle ClickCounter Of Fiber Node update

In the previous article, I introduced nextUnitOfWork The role of global variables .

nextUnitOfWork To keep the workInProgress tree One of them has a job to deal with Fiber Reference to node .nextUnitOfWork It will point to the next one Fiber The reference to a node is either null. have access to nextUnitOfWork Variable to determine whether there is a way to complete the work Fiber node .

We assume and call setState,React take setState The callback for is added to ClickCounter Of Fiber Node updateQueue Field and schedule the work .React Into the render( Rendering ) Stage . It is from HostRoot Nodes start , Use renderRoot Ergodic function Fiber Trees . It will skip the ones that have been dealt with Fiber node , Until you find the node where the work has not been completed . here , only one Fiber Node has unfinished work , Namely ClickCounter Fiber node .

Fiber The first node of the tree is a special type of node , be called HostRoot. It is created internally , Is the parent of the topmost component

be-all “work” Will be in Fiber Node backup . The backup is stored in alternate Field . If the backup node has not been created ,React Before processing updates , Use createWorkInProgress Function to create a backup . hypothesis nextUnitOfWork Have ClickCounter Of Fiber Reference to node .

beginWork

First Fiber Get into beginWork function .

because beginWork The function is every Fiber Nodes will execute . So if you need to debug render Phase of the source code , This is a good place to place breakpoints . I ( finger Max) Do that all the time .

beginWork Inside the function is a huge switch sentence ,switch Statement passing Fiber Node tag attribute , Judge Fiber The type of node . Then execute the corresponding function to perform the work .

Our node is CountClicks Component's Fiber node , So it's going to enter ClassComponent The branch statement of

function beginWork(current$$1, workInProgress, ...) {
...
switch (workInProgress.tag) {
...
case FunctionalComponent: {...}
case ClassComponent:
{
...
return updateClassComponent(current$$1, workInProgress, ...);
}
case HostComponent: {...}
case ...
}

And then we go into updateClassComponent function

stay updateClassComponent Function , Judge whether the component is rendering for the first time , Or get back to work (render Stages can be interrupted ) Or update .React Either create an instance and mount the component , Or just update it .

function updateClassComponent(current, workInProgress, Component, ...) {
...
const instance = workInProgress.stateNode;
let shouldUpdate;
if (instance === null) {
...
// If the example is null, We need to construct instances
constructClassInstance(workInProgress, Component, ...);
mountClassInstance(workInProgress, Component, ...);
shouldUpdate = true;
} else if (current === null) {
// After starting over , We already have an instance that can be reused .
shouldUpdate = resumeMountClassInstance(workInProgress, Component, ...);
} else {
// It's just an update
shouldUpdate = updateClassInstance(current, workInProgress, ...);
}
return finishClassComponent(current, workInProgress, Component, shouldUpdate, ...);
}

Handle CountClicks Fiber Update

after beginWork and updateClassComponent function , We already have ClickCounter Instances of components , We are now entering updateClassInstance.updateClassInstance The function is React Where most of the class components work . Here are the most important operations performed in the function ( In order of execution ):

  1. perform UNSAFE_componentWillReceiveProps Life cycle function
  2. perform Fiber Nodes in the updateQueue The update queue for , Generate new state
  3. Use the new state, perform getDerivedStateFromProps And get the results
  4. perform shouldComponentUpdate Determine if the component needs to be updated . If it is false, Skip the whole render Handle , Including this component and its subcomponents . If it is true, Continue to update .
  5. perform UNSAFE_componentWillUpdate Life cycle function
  6. add to effect Used to trigger componentDidUpdate Life cycle function
  7. Update... On component instances state and props
Even though componentDidUpdate Of effect stay render Phase add , But the method will be in the next commit The stage is executed

state and props It should be in the render Method is updated before calling , because render The output of a method usually depends on state and props, If we don't , It will return the same output each time .

// Simplified code
function updateClassInstance(current, workInProgress, ctor, newProps, ...) {
// Instances of components
const instance = workInProgress.stateNode;
// Previous props
const oldProps = workInProgress.memoizedProps;
instance.props = oldProps;
if (oldProps !== newProps) {
// If the current props And before props There are differences , perform UNSAFE_componentWillReceiveProps
callComponentWillReceiveProps(workInProgress, instance, newProps, ...);
}
// Update queue
let updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
// Execute update queue , Get a new state
processUpdateQueue(workInProgress, updateQueue, ...);
// Get the latest state
newState = workInProgress.memoizedState;
}
// Use the latest state, call getDerivedStateFromProps
applyDerivedStateFromProps(workInProgress, ...);
// Get the latest state(getDerivedStateFromProps It may be updated state)
newState = workInProgress.memoizedState;
// perform shouldComponentUpdate, Determine if the component needs to be updated
const shouldUpdate = checkShouldComponentUpdate(workInProgress, ctor, ...);
if (shouldUpdate) {
// If you need to update the execution UNSAFE_componentWillUpdate Life cycle function
instance.componentWillUpdate(newProps, newState, nextContext);
// And add effect, stay commit The phase will execute componentDidUpdate,getSnapshotBeforeUpdate
workInProgress.effectTag |= Update;
workInProgress.effectTag |= Snapshot;
}
// to update props and state
instance.props = newProps;
instance.state = newState;
return shouldUpdate;
}

The code snippet above is simplified code , For example, before calling a lifecycle function or adding effect.React Use typeof The operator detects whether the component implements this method . for example React Check to see if componentDidUpdate, stay effect Before you add

if (typeof instance.componentDidUpdate === 'function') {
workInProgress.effectTag |= Update;
}

well , Now we know ClickCounter Of Fiber Nodes in the render( Rendering ) Stage , Did those operations . Now let's see Fiber How the value on the node is changed . stay React When starting work ,ClickCounter Component's Fiber The nodes are as follows :

{
effectTag: 0,
elementType: class ClickCounter,
firstEffect: null,
memoizedState: {count: 0},
type: class ClickCounter,
stateNode: {
state: {count: 0}
},
updateQueue: {
baseState: {count: 0},
firstUpdate: {
next: {
payload: (state, props) => {…}
}
},
...
}
}

When the work is done , We get the following Fiber node

{
effectTag: 4,
elementType: class ClickCounter,
firstEffect: null,
memoizedState: {count: 1},
type: class ClickCounter,
stateNode: {
state: {count: 1}
},
updateQueue: {
baseState: {count: 1},
firstUpdate: null,
...
}
}

Look at the contrast between the two .memoizedState The property value of is determined by 0 Change into 1.updateQueue Of baseState The property value of is determined by 0 Change into 1.updateQueue No queue updates ,firstUpdate by null. And we modify effectTag Value , It marks where we are commit Side effects of phase execution .

effectTag from 0 Change into 4,4 In binary, it's 0b00000000100, This means that the third bit is set , And this representative Update

export const Update = 0b00000000100;

summary ,ClickCounter Component's Fiber node , stay render The phase calls the pre mutation life cycle method , to update state And defining side effects .

ClickCounter Fiber Sub coordination of

After finishing the above work ,React Get into finishClassComponent function , This is a React Invoke component's render Method , And apply to the child diff The place of algorithm .React The document is right diff The algorithm has a general overview .

If you know more about , We can know React Medium diff The algorithm will actually React Elements and Fiber Nodes are compared . The process is very complicated ( The author of the original text does not give too much narration here ), In our case ,render Method returns React Array of elements , So if you want more details, you can check out React Source code reconcileChildrenArray function .

There are two important things to understand at this time .

  1. React In the process of sub coordination , Create or update the child element's Fiber node . The element is made up of render return .finishClassComponent Method returns a reference to the first child of the current node . References are assigned to nextUnitOfWork Variable , And then in workLoop Intermediate processing .
  2. React Updated child's props, It's part of the parent's job . So , It is used from render Method React The data in the element .

for example ,React Before sub coordination ,span Corresponding Fiber node

{
stateNode: new HTMLSpanElement,
type: "span",
key: "2",
memoizedProps: {children: 0}, // Last used for rendering props
pendingProps: {children: 0}, // Updated props, Need to be used for dom And subcomponents
...
}

This is the call render Return after method React Element structure ,Fiber Nodes and returned React Elemental props It's a little different , Creating Fiber Node backup ,createWorkInProgress The function will React The updated data of the element is synchronized to Fiber Node .(Fiber All the work on is done on the backup node )

{
$$typeof: Symbol(react.element)
key: "2"
props: {children: 1}
ref: null
type: "span"
}

ClickCounter After the component completes the sub coordination ,span Elemental Fiber The node will be updated , The structure is as follows :

{
stateNode: new HTMLSpanElement,
type: "span",
key: "2",
memoizedProps: {children: 0}, // Used to create output during the last rendering Fiber props.
pendingProps: {children: 1}, // Updated Fiber props. Need to be used for subcomponents and DOM Elements .
...
}

Later in the execution span Elemental Fiber When a node works , Will pendingProps copy to memoizedProps On , And add effects, convenient commit Phase update dom.

Okay , This is it. ClickCounter Component in render All the work performed in phase . because button The element is ClickCounter The first child element of a component , all button Elemental Fiber Nodes are assigned to nextUnitOfWork. because button Elemental Fiber The node is not working , therefore React Will take its brother node, namely span Elemental Fiber Nodes are assigned to nextUnitOfWork. The behavior here is completeUnitOfWork In the method .

Handle span Fiber Update

nextUnitOfWork At present, it points to span Fiber Spare node ( Because work is all about workInProgress tree The complete ). The steps and ClickCounter similar , We from beginWork Function to .

Yes span Elemental Fiber Node tag The attribute is HostComponent type ,beginWork Into the updateHostComponent Branch .( Contents of this part , And with the current version of React There's a conflict )

function beginWork(current$$1, workInProgress, ...) {
...
switch (workInProgress.tag) {
case FunctionalComponent: {...}
case ClassComponent: {...}
case HostComponent:
return updateHostComponent(current, workInProgress, ...);
case ...
}

span Fiber Sub coordination of

In our case ,span Of Fiber Nothing important happens in the sub coordination

span Fiber Finish the work

beginWork After completion ,span Fiber Get into completeWork. But before that React You need to update span Fiber Upper memoizedProps. In sub coordination ,React Updated span Fiber Of pendingProps Field .( This part of the content has been compared with the present React Version conflict )

{
stateNode: new HTMLSpanElement,
type: "span",
key: "2",
memoizedProps: {children: 0},
pendingProps: {children: 1},
...
}

span Fiber Of beginWork After completion , Will be pendingProps Update to memoizedProps On

function performUnitOfWork(workInProgress) {
...
next = beginWork(current$$1, workInProgress, nextRenderExpirationTime);
workInProgress.memoizedProps = workInProgress.pendingProps;
...
}

And then call completeWork Method ,completeWork There is also a big problem inside the method switch sentence

function completeWork(current, workInProgress, ...) {
...
switch (workInProgress.tag) {
case FunctionComponent: {...}
case ClassComponent: {...}
case HostComponent: {
...
updateHostComponent(current, workInProgress, ...);
}
case ...
}
}

because span Fiber yes HostComponent, So it will execute updateHostComponent function , In this function React Do the following :

  1. Get ready DOM to update
  2. They are added to span Fiber Of updateQueue
  3. add to DOM The updated effects

Before performing these operations ,Fiber The node structure :

{
stateNode: new HTMLSpanElement,
type: "span",
effectTag: 0
updateQueue: null
...
}

After the operation Fiber Node structure :

{
stateNode: new HTMLSpanElement,
type: "span",
effectTag: 4,
updateQueue: ["children", "1"],
...
}

Be careful Fiber Node effectTag value , from 0 Change into 4,4 In binary, it's 100, This is a Update The representation of side effects , This is a commit Stage React Work to be done , and updateQueue The load of the field (payload) Will be used in the update .

React In order to complete the sub element work and ClickCounter After the work , It's done. render Stage . here React take workInProgress tree( The backup node , render Phase update tree ) Assigned to FiberRoot Node finishedWork attribute . This is a new tree that needs to be refreshed on the screen , It can be render Immediately after the phase , Or hang up idle time waiting for the browser .

effects list

In our case span Nodes and ClickCounter node , Has side effects .HostRoot(Fiber A node of the tree ) Upper firstEffect Attribute points to span Fiber node .

React stay compliteUnitOfWork Create in function effects list This is a effects Of Fiber Trees .effects It contains : to update span The text of , call ClickCounter Life cycle function .

1.png

effects list Linear list :

2.png

commit Stage

commit Stage from completeRoot Function to , Before starting any work , It will FiberRoot Of finishedWork Property is set to null.

commit The phases are always synchronized , So it can be safely updated HostRoot To instruct commit Here we go .

commit Stage , yes React to update DOM, And where to call lifecycle methods . So React Will traverse the previous render Stage structured effects list, And apply them .

stay render Stage ,span and ClickCounter Of effects as follows :

{ type: ClickCounter, effectTag: 5 }
{ type: 'span', effectTag: 4 }

ClickCounter Fiber Node effectTag The value is 5,5 The binary of is 101, The third bit is set to 1, This is a Update The representation of side effects , We need to call componentDidUpdate Life cycle approach . The lowest is also 1, The surface of the Fiber Nodes in the render All the work in this stage has been completed .

span Fiber Node effectTag The value is 5,5 The binary of is 101, The third bit is set to 1, This is a Update The representation of side effects , We need to update span Elemental textContent.

application effects

application effects In function commitRoot Finish in ,commitRoot It's made up of three sub methods .

function commitRoot(root, finishedWork) {
commitBeforeMutationLifecycles()
commitAllHostEffects();
root.current = finishedWork;
commitAllLifeCycles();
}

Every sub method loops effects list, And check effects The type of .

The first function commitBeforeMutationLifeCycles Check Snapshot effects, And call getSnapshotBeforeUpdate function , But we are ClickCounter There is no... Added to the component getSnapshotBeforeUpdate Life cycle function , therefore React Not in render Phase to add this role , So in our case , This method does nothing .

DOM to update

Next is commitAllHostEffects, In this function span The text content of will be from 0 To 1.ClickCounter Fiber The node has no action .

commitAllHostEffects The interior is also a big one switch, according to effects The type of , Apply the corresponding operation :

function updateHostEffects() {
switch (primaryEffectTag) {
case Placement: {...}
case PlacementAndUpdate: {...}
case Update:
{
var current = nextEffect.alternate;
commitWork(current, nextEffect);
break;
}
case Deletion: {...}
}
}

Enter into commitWork function , Recently entered updateDOMProperties Method , It will be used in render Phase added in Fiber nodes updateQueue Load in attribute (payload), And apply it to span Elemental textContent Attribute .

function updateDOMProperties(domElement, updatePayload, ...) {
for (let i = 0; i < updatePayload.length; i += 2) {
const propKey = updatePayload[i];
const propValue = updatePayload[i + 1];
if (propKey === STYLE) { ...}
else if (propKey === DANGEROUSLY_SET_INNER_HTML) {...}
else if (propKey === CHILDREN) {
setTextContent(domElement, propValue);
} else {...}
}

application DOM After the update ,React take finishedWork Upper workInProgress tree Assigned to HostRoot. take workInProgress tree Set to current tree.

root.current = finishedWork;

Call the post lifecycle function

The last remaining function is commitAllLifecycles. stay render Stage React Will Update effects Add to ClickCounter In the component ,commitAllLifecycles Function is where the post mutation lifecycle method is called .

function commitAllLifeCycles(finishedRoot, ...) {
while (nextEffect !== null) {
const effectTag = nextEffect.effectTag;
if (effectTag & (Update | Callback)) {
const current = nextEffect.alternate;
commitLifeCycles(finishedRoot, current, nextEffect, ...);
}
if (effectTag & Ref) {
commitAttachRef(nextEffect);
}
nextEffect = nextEffect.nextEffect;
}
}

Life cycle function in commitLifeCycles Call in function .

function commitLifeCycles(finishedRoot, current, ...) {
...
switch (finishedWork.tag) {
case FunctionComponent: {...}
case ClassComponent: {
const instance = finishedWork.stateNode;
if (finishedWork.effectTag & Update) {
if (current === null) {
instance.componentDidMount();
} else {
...
instance.componentDidUpdate(prevProps, prevState, ...);
}
}
}
case HostComponent: {...}
case ...
}

You can see in this method ,React Call... For the first rendered component componentDidMount Method .

summary

Max Koretskyi The content of the article is more , So finally, summarize the knowledge :

  1. Every component has an associated updater( Updater ). The updater acts as a component and React core The bridge between . This allows setState stay ReactDOM,React Native, Server side rendering and test cases are implemented in different ways .
  2. about class Components ,updater( Updater ) yes classComponentUpdater
  3. When updating ,updater( Updater ) Will be in Fiber Node updateQueue Properties of the , Add update queue .
  4. render( Rendering ) Stage ,React From HostRoot To traverse the Fiber Trees , Skip what has been processed Fiber node , Until we find it and work Unfinished Fiber node . All the work is in Fiber Node backup , The backup is stored in Fiber Node alternate Field . If alternate The field hasn't been created yet , React Will be used before handling work createWorkInProgress establish alternate Field ,createWorkInProgress The function will React The state of the element is synchronized to Fiber Node .
  5. nextUnitOfWork To keep the workInProgress tree One of them has a job to deal with Fiber Reference to node .
  6. Fiber Nodes enter beginWork function ,beginWork The function will Fiber The node type performs the corresponding work ,class Components will be updateClassComponent Function execution .
  7. every last Fiber Nodes will execute beginWork function . after beginWork function , Components are either created as component instances , Or just update the component instance .
  8. after beginWork, updateClassComponent after , Get into updateClassInstance, Here are the processing class components work The place of .( The following operations are performed in sequence )

    • perform UNSAFE_componentWillReceiveProps Life cycle function
    • perform Fiber Nodes in the updateQueue The update queue for , Generate new state
    • Use the new state, perform getDerivedStateFromProps And get the return result
    • perform shouldComponentUpdate Determine if the component needs to be updated . If it is false, Skip the whole render Handle , Including this component and its subcomponents . If it is true, Continue to update .
    • perform UNSAFE_componentWillUpdate Life cycle function
    • add to effects Used to trigger componentDidUpdate Life cycle function (commit The stage will trigger )
    • Update... On component instances state and props
  9. render Stage class The components mainly do : Call the leading mutation lifecycle method , to update state, Definition related effects.
  10. complete updateClassInstance After the end ,React Get into finishClassComponent, here React Invoke component's render Method , And apply to the child diff The place of algorithm ( The place of sub coordination ).
  11. The child coordinator creates or updates the child element's Fiber node , The element is made up of render Method returns , The attributes of child elements are synchronized to the attributes of child elements Fiber Node .finishClassComponent Will return the first child element Fiber node , And assigned to nextUnitOfWork, After convenience workLoop Continue to deal with ( After that, the node of the child node ).
  12. Update child elements props Is part of the work of the parent element .
  13. render After the stage is completed .React take workInProgress tree( The backup node , render Phase update tree ) Assigned to FiberRoot Node finishedWork attribute .
  14. commit Before the stage ,FiberRoot Of finishedWork Property is set to null.
  15. commit The phases are synchronous , yes React to update DOM, And where to call lifecycle methods ( Side effects of application ).

Reference resources

版权声明
本文为[Zhang Yue]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/02/20210222183304302y.html

  1. vue判断elementui中el-form是否更新变化,变化就提示是否保存,没变就直接离开
  2. 算法题:两数之和——JavaScript及Java实现
  3. 高性能 Nginx HTTPS 调优
  4. Why Vue uses asynchronous rendering
  5. day 31 jQuery进阶
  6. day 30 jQuery
  7. CSS whimsy -- using background to create all kinds of wonderful backgrounds
  8. Why are more and more people learning front end?
  9. What do you do with 4K front-end development?
  10. 8 years of front-end development knowledge precipitation (do not know how many words, keep writing it...)
  11. What is the annual salary of a good web front end?
  12. Front end novice tutorial! How to get started with web front end
  13. Will the front end have a future?
  14. Is the front end hard to learn?
  15. Seven new Vue combat skills to improve efficiency in 2021!
  16. Is front end learning difficult?
  17. How about the process of Web front-end development and self-study?
  18. Front end learning route from zero basis to proficient
  19. What is the basis of learning front end?
  20. What knowledge points need to be learned for self-study front end? How long can I become a front-end Engineer?
  21. An inexperienced front-end engineer, what are the common problems when writing CSS?
  22. HttpServletRequest get URL (parameter, path, port number, protocol, etc.) details
  23. Springboot starts http2
  24. Enabling http2.0 in spring boot
  25. JQuery:JQuery基本语法,JQuery选择器,JQuery DOM,综合案例 复选框,综合案例 随机图片
  26. Using JavaScript in Safari browser history.back () the page will not refresh after returning to the previous page
  27. vue.js Error in win10 NPM install
  28. In less than two months, musk made more than $1 billion, more than Tesla's annual profit
  29. Springboot starts http2
  30. Vue event bus
  31. JQuery easy UI tutorial: custom data grid Pagination
  32. Using okhttp and okhttpgo to obtain onenet cloud platform data
  33. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control
  34. HTTP 1. X learning notes: an authoritative guide to Web Performance
  35. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control
  36. HTTP 1. X learning notes: an authoritative guide to Web Performance
  37. JQuery:JQuery基本语法,JQuery选择器,JQuery DOM,综合案例 复选框,综合案例 随机图片
  38. Event bubble and capture in JavaScript
  39. The root element is missing solution
  40. Event bubble and capture in JavaScript
  41. Configure the certificate to enable ngnix to publish the trusted website of HTTPS
  42. Javascript数据类型
  43. HTTP interface debugging tool! 48000 star HTTP command line client!
  44. Parameter encryption of front end URL link band
  45. HTTP interface debugging tool! 48000 star HTTP command line client!
  46. Three front end frameworks: data binding and data flow
  47. Reading Axios source code (1) -- exploring the realization of basic ability
  48. Event bubble and capture in JavaScript
  49. 【微前端】微前端最終章-qiankun指南以及微前端整體探索
  50. R & D solution e-Car front end monitoring system
  51. [JS] 877 - 35 wonderful knowledge of JavaScript, long experience!
  52. R & D solution e-Car front end monitoring system
  53. High performance nginx HTTPS tuning - how to speed up HTTPS by 30%
  54. 解决ajax跨域问题【5种解决方案】
  55. Top ten classic sorting of JavaScript
  56. HTTP 1. X learning notes: an authoritative guide to Web Performance
  57. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control component
  58. My http / 1.1 is so slow!
  59. Why Vue uses asynchronous rendering
  60. The response status was 0. Check out the W3C XMLHttpRequest Level 2 spec for