As we all know, programmers are after one word: quick! Yesterday Vue3.0 was officially released, excited heart, trembling hands, touched my hair, well, not bad. It is said that Vue3.0 is 1.2 times better than vue2.x. Why is it so fast? Vue3.0 does the following

  1. Diff algorithm optimization
  2. Static lifting (hoistStatic)
  3. Event Listener Cache
  4. SSR optimization (see mood update)

Diff algorithm optimization

Diff algorithm of Vue2. X

Vue2. X’s DIff algorithm is called full comparison. As the name implies, vDom comparison is performed from beginning to end when data changes, even if some content is permanent and fixed.

The DIff algorithm of Vue3.0

Vue3.0’s diff algorithm has a gadget called PatchFlag. What is a static flag?

To put it simply, if your content changes, I will give you a flag. Next time when the data is updated, I will directly compare you, and I will not compare those that are not marked

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div".null, [
    _createVNode("p".null."'HelloWorld'"),
    _createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
    										   // The 1 above is the static tag))}Copy the code

So you’re going to have to ask, why is it a 1?

TEXT = 1 // Dynamic text node
CLASS=1<<1.1 // 2// dynamic class
STYLE=1<<2.// 4 // dynamic style
PROPS=1<<3.// 8 // Dynamic properties, but without class name and style
FULLPR0PS=1<<4.// 16 // Has a dynamic key property. When the key changes, a full diff comparison is required.
HYDRATE_ EVENTS = 1 << 5.// 32 // Node with listening events
STABLE FRAGMENT = 1 << 6.// 64 // A fragment that does not change the order of child nodes
KEYED_ FRAGMENT = 1 << 7.// 128 // Fragment with key attribute or fragment with key
UNKEYED FRAGMENT = 1<< 8.// 256 // The child node does not have a key fragment
NEED PATCH = 1 << 9.// 512 // A node will only compare non-props
DYNAMIC_SLOTS = 1 << 10 // 1024 // Dynamic slot
HOISTED = -1 // Static node
Exit optimization mode in diff algorithm
BALL = -2
Copy the code

Static lifting (hoistStatic)

In Vue3.0, static promotion will be performed for elements that do not participate in the update and will only be created once. You can reuse the same code before turning on static promotion

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div".null, [
    _createVNode("p".null."'HelloWorld'"),
    _createVNode("p".null."'HelloWorld'"),
    _createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* TEXT */)))}Copy the code

Compiling results after static promotion is enabled

const _hoisted_1 = /*#__PURE__*/_createVNode("p".null."'HelloWorld'", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createVNode("p".null."'HelloWorld'", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div".null, [
    _hoisted_1,
    _hoisted_2,
    _createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* TEXT */)))}Copy the code

When static promotion is enabled, the two p tags labeled helloWorld are declared outside and used directly. This will be faster

Event listener cache

By default, onClick is treated as a dynamic binding, so it is tracked every time it changes, but because it is the same function, it is not tracked, so it is cached and reused in the DOM structure

<div>
  <button @click = 'onClick'>Am I</button>
</div>
Copy the code

Before enabling event listener caching:


export const render = /*#__PURE__*/_withId(function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div".null, [
    _createVNode("button", { onClick: _ctx.onClick }, "点我".8 /* PROPS */["onClick"])
    									     // PROPS=1<<3,// 8 // dynamic properties, but without class names and styles))})Copy the code

There is an 8 here, indicating that the node has a static flag, which will cause diff algorithm to compare the difference, so it will waste time after the event listener cache is enabled:

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div".null, [
    _createVNode("button", {
      onClick: _cache[1] || (_cache[1] = (. args) = >(_ctx.onClick(... args))) },"点我")))}Copy the code

As you can see, when the event listener cache is enabled, there are no static tags, which is much faster