Vue2 source code analysis

The diff algorithm and the principle of response formula are mainly recorded here

The Diff algorithm

Vue source code borrowed from snabbDOM (virtual DOM library)

Diff algorithm node comparison criterion

  • The diff algorithm makes a fine comparison between the new virtual DOM and the old virtual DOM and finally re-renders the comparison result to reflect the real DOM

  • The DIff algorithm performs fine comparison only for the same virtual DOM, otherwise only violent inserts and inserts will be performed

  • The DIff algorithm will only compare between layers and not across layers

Optimization strategy of diff algorithm

Four Pointers:

  • OldStartIdx (old front pointer)
  • NewStartIdx (new front pointer)
  • OldEndIdx (old after pointer)
  • NewEndIdx (new post-pointer)

Diff algorithm pointer matching lookup rule:

There are four matching search rules: Only one match is hit in sequence. If none of the four matches is hit, the loop is re-executed

  • 1, new before and old before (new node, new before and after the node included[New before, new after]Insert new node before old pointer.
  • 2, after the new and old (delete the node, the old before and after the node contained[Old before, old after]Delete)
  • 3. New back and old front (move the position, insert the old front to the old back)
  • 4. New before and old after (move the position, insert the old after to the old before)

Exit of hit failure:

oldStartIdx>oldEndIdx && newStartIdx>newEndIdx
Copy the code

1, the new and the old

Old front -> A A <- new front B B old back -> C M N C <- new backCopy the code

When the new front and the old front hit, the new front and the old front continue to move down

A A B B old before -> old after -> C M <- new before N C <- new afterCopy the code

When the new and old front Pointers do not match, it judges whether the new and old rear Pointers are matched. If so, the two Pointers move up

A A old back -> B B old front -> C M <- new front N <- new back CCopy the code

The loop ends with oldStartIdx>oldEndIdx, and we find that the element [M, N] contained in the new front and new back Pointers is the element we need to add

New rule: We want to insert the new element before the old pointer

New queen and old queen

Old front -> A C <- new front B D <- new rear C old rear -> DCopy the code

When the old and new front Pointers do not match, judge whether the new and old rear Pointers match, and move the pointer up if they match

Old front -> A C <- new front <- new rear B D old rear -> C DCopy the code

When the old and new front Pointers do not match, judge whether the new and old rear Pointers match, and move the pointer up if they match

<- new - old -> A C <- new - old -> B D C DCopy the code

The newStartIdx>newEndIdx loop ends, and we find that the elements [A, B] contained in the old before and after Pointers are the elements we need to delete, so we traverse the pointer to delete both elements

The new and the old

Old front -> A C <- new front B B old back -> C A <- new backCopy the code

When the old front doesn’t match the new front and the old back doesn’t match the new back, we try to match the old front and the new back, after the hit we insert the old front into the old back and move the pointer

C <- new old -> B B <- new old -> C A ACopy the code
C <- new <- new after B Old before -> old after -> C A B ACopy the code

Both sides of the old and new hit move pointer end the loop

New before and old after

Old before -> A C <- new before B A old after -> C B <- new afterCopy the code

The current three hits all fail, but with the new before and the old after fourth hit, we insert the old after node before the old before and move the pointer accordingly.

C Old front -> A C Old back -> B A <- new front B <- new backCopy the code

And then it’s the first hit before the new hit and the first hit before the old hit, ending the loop on both sides.

All four are dead

When none of the four methods are hit, we need to perform the following operation. For performance optimization, we use Map to cache the indexes of all the old nodes.

If the new node is a new node, we cannot find its corresponding index in the old node, indicating that the new node needs to be inserted.

If the new node can find the corresponding index in the old node, the node needs to be moved, and the new front pointer needs to be moved back, ending the loop and removing the excess elements

The old front -> A D <- new front new rear B old rear -> CCopy the code

We can see that none of the four hits are possible in this case. We need to insert D in front of the old pointer, move the new pointer to end the loop, and remove the old pointer to the ABC element covered by the old pointer

Old before -> A B <- new before new after B old after -> CCopy the code

In this case, we need to insert the element in the new node before the old node, move the pointer before the new node to end the loop, and delete the element ABC covered by the old pointer and the old pointer.

Response principle

Object.defineproperty (obj, key, {}): Defines a new property directly on an Object, or modifies an existing property of an Object and returns the Object

let obj = {}
Object.defineProperty(obj, 'a', {
  value: 2
})


// Data hijacking
Object.defineProperty(obj, 'a', {
  get(){}})Copy the code

Detection object

Detection array

Vue has rewritten seven of Array’s methods

  • 1, push
  • 2, pop
  • 3, unshift
  • 4, the shift
  • 5, splice
  • 6, sort
  • 7, reverse

The object.create () method creates a new Object, using an existing Object to provide the __proto__ of the newly created Object

The object.setProtoTypeof () method sets the Prototype of a specified Object (that is, the internal [[Prototype]] property) to another Object or null

const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)

Object.setPrototypeOf(o, arrayMethods)
// o.__proto__ = arrayMethods
Copy the code