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

  1. When we’re executingthis.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.
  2. The watcher update method calls queueWatcher to place the watcher in the global queue.
  3. 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).
  4. 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:

  1. Batch updates provide a significant performance boost
  2. Make sure state is consistent with props, because you don’t know props until the parent component rerenders
    1. Props cannot synchronize because of asynchronous rendering.
    2. 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.
  3. 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!