This is the 20th day of my participation in the August Text Challenge.More challenges in August
preface
Of the modern front-end frameworks, vue and React are the most popular. The popularity of modern front-end frameworks has greatly improved the engineering capabilities and efficiency of front-end development, as well as the ecological solutions to complex and common problems. Vue and React are data-driven views, so the policy adopted by the update view is reflected in the API. Vue is nextTick, and React is setState.
Vue.nextTick
- There is this vUE code
this.msg = 'hello'
this.msg = 'hello'
this.count = 1
this.color = 'red'
Copy the code
Q: If all three variables are used in the template, how many page renders are performed
A: Once
Because we all know that batch updates can greatly improve performance. That said, synchronous rerendering is inefficient in many cases if we know we’re likely to get multiple updates, so we’re better off updating in batches.
How is this implemented in VUE?
We only consider the implementation of nextTick (not the strategy to collect dependencies and how to handle DOM diff)
Here is the slightly simplified source code for nextTick
export function nextTick(cb, ctx) {
let _resolve;
callbacks.push(() = > {
if (cb) {
cb.call(ctx);
} else if(_resolve) { _resolve(ctx); }});if(! pending) { pending =true;
/ / execution watcher
timerFunc(); // Clean the queue
}
if(! cb &&typeof Promise! = ="undefined") {
return new Promise((resolve) = > {
_resolve = resolve; // Assign the resovle function to _resolve, when all the functions in the callbacks callback queue have finished executing.}); }}Copy the code
And the queueWatcher method on which the function depends
export function queueWatcher(watcher: Watcher) {
const id = watcher.id;
// Watch will only join once, this is a de-weight operation.
if (has[id] == null) {
has[id] = true;
// Put the current watcher in the queue array if no queue refresh operation is being performed
if(! flushing) { queue.push(watcher); }else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
let i = queue.length - 1;
while (i > index && queue[i].id > watcher.id) {
i--;
}
queue.splice(i + 1.0, watcher);
}
// queue the flush
if(! waiting) { waiting =true;
if(process.env.NODE_ENV ! = ="production" && !config.async) {
flushSchedulerQueue();
return; } nextTick(flushSchedulerQueue); }}}Copy the code
Execute the process
- When we’re executing
this.msg = 'hello'
MSG, the set method of this._data. MSG will call the notify method of this property and notify the Watcher in the dePS of this property to execute. In this case the watcher is the render Watcher. - The watcher update method calls queueWatcher to place the watcher in the global queue.
- Put the flushCallbacks function into NextTick and wait until the main thread is finished to execute the flushCallbacks function. That is, each item in the Nexttick queue is executed using the run method, and the Nexttick method is executed using a microtask (fallback to setTimeout).
- If the user uses the Nexttick method, place the callback passed in by the user to the last item in the queue array, and when all the watcher.run runs have been executed, the callback passed in by the user is executed
When we are in an eventLoop, if we have this. MSG = ‘xx’, because the MSG attribute only has a unique Watcher ID, it will be de-duplicated, leaving the last one.
When this. MSG = ‘xx’ is executed, the DOM does not refresh immediately, because we can see that the DOM updates asynchronously, but the MSG value changes synchronously, which is normal because we change the value, the value should be changed immediately. But that’s not the case in React.
setState
When changing a view, React doesn’t have an object proxy like vue. We need to explicitly call the setState API to update the data and drive the view. After changing the view in performance, we BatchingUpdate the merged data in batch mode. This is then optimized at the render DOM layer through dom diff and other strategies, as it incurs a significant performance cost if the real DOM is re-rendered every time the state changes.
Why not get the latest data after setState
However, unlike VUE, the latest state data cannot be obtained after setState is executed. Why is that?
Redux author’s response
RFClarification: why is setState
asynchronous?
To sum up:
- Batch updates provide a significant performance boost
- Make sure state is consistent with props, because you don’t know props until the parent component rerenders
- Props cannot synchronize because of asynchronous rendering.
- In Vue, props couldn’t synchronize either, but why did Vue let it get the value immediately? Probably because vue’s smallest render unit is a component, Watcher is able to accurately locate components for updates.
- React ensures that all states are safe.
SetState performance in different scenarios
SetState can be asynchronous or synchronous in different scenarios.
- SetState is only asynchronous in React synthetic time and life cycle functions, and synchronous in non-synthetic events and setTimeout.
Because the react synthesis event and hook function are executed before the update, this asynchronous means that the latest result is not available before the update, and the setState implementation is asynchronous. “Asynchronous” means batching update. You get performance optimizations that you don’t get with non-synthetic events and setTimeout.
If an identical property is updated within an event loop in a composite event or hook function, the merge occurs
this.setState({
num: 456
})
this.setState({
num: 567
})
// The merge will take place and only the setState of the latter will be executed
Copy the code
Gets the latest state after setState
Use componentDidUpdate or setState(updater, callback) to retrieve the state after the change. If you need to change a state using the previous state, You need to use the above method.)
conclusion
The above is my superficial understanding of the update strategy mechanism of VUE and React on the API. As a newcomer to React, I still cannot have a comprehensive understanding of the overall implementation process of the framework, so THERE is no analysis of the source code and I just express some superficial views. Welcome to correct and discuss the wrong expressions. Come on!