Vue3’s core Typescript, Proxy responsiveness, Composition solutions and repeated crossoverings have all been dissected in great articles. I’ll summarize the virtual Dom section and compare it to React. The VDOM rewrite is also a big reason why Vue3 performs so well

Overall especially the process of live broadcast, a few big brothers have summed up the thief stick, move directly

  1. This article is enough to understand the Vue3 source code
  2. Vue 3.0 this charming little goblin, what is good in the end? (Update principle comparison)
  3. Note: Yuyuxi talked about this in Vue3.0 Beta…

The virtual DOM of Vue3

First of all, the conclusion is that with static marker, upadTE performance is improved by 1.3~2 times, and SSR performance is improved by 2~3 times. How to do it

The static tag for compiling the template

Let’s look at a very common piece of code

<div id="app">
    <h1>Technology to touch the fish</h1>
    <p>It's a nice day today</p>
    <div>{{name}}</div>

</div>

Copy the code

It is analyzed in VUE2

function render() {
  with(this) {
    return _c('div', {
      attrs: {
        "id": "app"
      }
    }, [_c('h1', [_v("Technical fish")]), _c('p', [_v("It's a beautiful day today.")]), _c('div', [_v(
      _s(name))])])
  }
}

Copy the code

The first two tags are completely static and will not change in subsequent rendering. Vue2 still uses _C newly built VDOM, which needs to be compared during diff, which has some additional performance loss

Let’s look at the parsing results in VUe3

import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", { id: "app" }, [
    _createVNode("h1".null."Technical fish"),
    _createVNode("p".null."It's a beautiful day today."),
    _createVNode("div".null, _toDisplayString(_ctx.name), 1 /* TEXT */)))}// Check the console for the AST

Copy the code

The fourth parameter of the last _createVNode, 1, is only truly tracked. Static nodes do not need to be traversed. This is the main source of vuE3’s excellent performance

<div id="app">
    <h1>Technology to touch the fish</h1>
    <p>It's a nice day today</p>

    <div>{{name}}</div>
    <div :class="{red:isRed}">Fishing in character</div>
    <button @click="handleClick">Poking me</button>
    <input type="text" v-model="name">
    
</div>

Copy the code

The results of parsing are previewed online


import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", { id: "app" }, [
    _createVNode("h1".null."Technical fish"),
    _createVNode("p".null."It's a beautiful day today."),
    _createVNode("div".null, _toDisplayString(_ctx.name), 1 /* TEXT */),
    _createVNode("div", {
      class: {red:_ctx.isRed}
    }, "Touch the fish".2 /* CLASS */),
    _createVNode("button", { onClick: _ctx.handleClick }, "Poking me".8 /* PROPS */["onClick"]]))}// Check the console for the AST

Copy the code

_createVNode: props, props, props, props, props, props, props Take a cue from the quitters

export const enum PatchFlags {
  
  TEXT = 1.// represents an element with a dynamic textContent
  CLASS = 1 << 1.// Represents an element with a dynamic Class
  STYLE = 1 << 2.// Represent dynamic styles (static, such as style="color: red", will also be promoted to dynamic)
  PROPS = 1 << 3.// represents an element with a non-class/style dynamic item.
  FULL_PROPS = 1 << 4.// An element that represents an item with a dynamic key, which is opposed to the three above
  HYDRATE_EVENTS = 1 << 5.// Represents an element with an event listener
  STABLE_FRAGMENT = 1 << 6.// represents a fragment whose suborder is unchanged.
  KEYED_FRAGMENT = 1 << 7.// represents a fragment with keyed or partially keyed child elements.
  UNKEYED_FRAGMENT = 1 << 8.// represents a fragment with no key binding
  NEED_PATCH = 1 << 9.// indicates that only elements that are not attribute fixes are required, such as refs or hooks
  DYNAMIC_SLOTS = 1 << 10.// represents an element with a dynamic slot
}
Copy the code

If you have both props and text bindings, you can use the bit-operation combination


<div id="app">
    <h1>Technology to touch the fish</h1>
    <p>It's a nice day today</p>
    <div :id="userid"">{{name}}</div>
</div>


Copy the code
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", { id: "app" }, [
    _createVNode("h1".null."Technical fish"),
    _createVNode("p".null."It's a beautiful day today."),
    _createVNode("div", {
      id: _ctx.userid,
      "\" ": ""
    }, _toDisplayString(_ctx.name), 9 /* TEXT, PROPS */["id"]]))}// Check the console for the AST

Copy the code

Text is 1, props is 8, and the combination is 9. We can use bitwise operation to determine whether to use text and props. As long as it is not 0, we need to compare

code

export const PLUGIN_EVENT_SYSTEM = 1;
export const RESPONDER_EVENT_SYSTEM = 1 << 1;
export const USE_EVENT_SYSTEM = 1 << 2;
export const IS_TARGET_PHASE_ONLY = 1 << 3;
export const IS_PASSIVE = 1 << 4;
export const PASSIVE_NOT_SUPPORTED = 1 << 5;
export const IS_REPLAYED = 1 << 6;
export const IS_FIRST_ANCESTOR = 1 << 7;
export const LEGACY_FB_SUPPORT = 1 << 8;

Copy the code

Event caching

The bound @click link will be cached

<div id="app">
  <button @click="handleClick">Poking me</button>
</div>

Copy the code

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", { id: "app" }, [
    _createVNode("button", {
      onClick: _cache[1] || (_cache[1] = $event= > (_ctx.handleClick($event)))
    }, "Poking me")))}Copy the code

The incoming event is automatically generated and cached as an inline function and then cached as a static node. This way, even if we write our own inline functions, we don’t have to repeat the render

Static ascension

code

<div id="app">
    <h1>Technology to touch the fish</h1>
    <p>It's a nice day today</p>
    <div>{{name}}</div>
    <div :class="{red:isRed}">Fishing in character</div>
</div>

Copy the code
const _hoisted_1 = { id: "app" }
const _hoisted_2 = _createVNode("h1".null."Technical fish".- 1 /* HOISTED */)
const _hoisted_3 = _createVNode("p".null."It's a beautiful day today.".- 1 /* HOISTED */)

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", _hoisted_1, [
    _hoisted_2,
    _hoisted_3,
    _createVNode("div".null, _toDisplayString(_ctx.name), 1 /* TEXT */),
    _createVNode("div", {
      class: {red:_ctx.isRed}
    }, "Touch the fish".2 /* CLASS */)))}Copy the code

Vdom for VuE3 and React Fiber

A lot of people talk about it being more and more like React, but it’s actually more and more like an API, representing both directions of the front end

Vue1.x

No VDOM, completely responsive, every data change, through a responsive notification mechanism for new Watcher work, just like the independent regiment size, every soldier enlisted and promoted, proactively notified our Old Li, easy to manage

As the project gets larger, too many Watcher can lead to performance bottlenecks

React15x

In the era of React15, there was no response, and the data changed. Diff the whole new data and the old data, calculate the difference, and then know how to modify the DOM. Just like Old Li’s command room has a model, every personnel change, by comparing the difference of all the people before and after, we know the change, which seems to involve a lot of calculation. But this immutable data structure is more friendly to large projects, and after the success of Vdom abstraction, it is possible to change to other platform render, whether it is to fight the devil or the military, with a Vdom mode

If the number of DOM nodes continues to increase and the diff time exceeds 16ms, it may cause a lag (60fps).

Vue2.x

Vdom was introduced to control the granularity, watcher notifications were made on the component level, and DIff was made on the component internal VDOM, so there would not be too many Watcher, and the size of VDOM would not be too large. The DIFF would exceed 16ms. It is really excellent, just like when the independent regiment became large, only the battalion commander and platoon commander level would be notified to Li. Internal diff managed by itself

React 16 Fiber

React went the other way. Since the main problem was diff causing the lag, React went the same way as CPU scheduling, turning the VDOM tree into a linked list, using the browser’s free time to do diff, and giving the browser control of the main process back if there was animation or user interaction over 16ms. Wait for idle to continue, especially like waiting for a goddess’s spare tire

Diff logic becomes a one-way linked list. Whenever the main thread is free, we will continue to do diff. If you look at requestIdleCallback, it will look like this from the browser’s perspective

About the code

requestIdelCallback(myNonEssentialWork);
// Wait for the goddess to be idle
function myNonEssentialWork (deadline) {
    // deadline.timeremaining ()>0
    // Diff is not a game
    while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    doWorkIfNeeded();
    }
    // The goddess is running out of time, return the goddess to 🀣
    if (tasks.length > 0){ requestIdleCallback(myNonEssentialWork); }}Copy the code

Vue3

If the React component shouldComponentUpdate component is defined by itself, why not change the default component to pure or memo? If the React component shouldComponentUpdate component is defined by itself? Maybe this is life

React gives you freedom and Vue makes you last, which is probably why both Vue and React are so popular in China now

With Proxy response + component internal VDOM + static markup, Vue3 controls the granularity of tasks in sufficient detail, so there is no need for time-slice

Life ah, only children study pros and cons every day, adults choose I want, but also look forward to React17 new features

Live broadcast details

During the final question period, I can’t avoid the problem of hair quantity, but I didn’t recommend what hair conditioner. I took a close look at it, and it seems that after the release of VUE3, the hairline of vuE3 has indeed improved. I wish you can have black hair while improving your technology

Small AD

Welcome to like attention, my main hobby is to touch fish, recommend a fish, this article is my morning to touch fish to write out, together with the technology to touch fish, recently ready to touch fish to write a VUE3 source code full analysis series