Detailed explanation of the data responsiveness principle of Vue

Detailed explanation of the data responsiveness principle of Vue

This article is mainly for those who do not understand or have not been exposed to the Vue responsive source code. Its main purpose is to have a basic understanding of the responsive principle of Vue. If you are asked such questions in an interview, you will know what the interviewer wants you to answer? PS: If there is anything wrong in the article, you are welcome to correct it.

Responsive understanding

Responsiveness, as the name implies, means that data changes will cause the view to be updated. This article mainly analyzes the implementation of object and array responsiveness in Vue2.0. We will leave dependency collection and view update to the next article.

In Vue, the responsive data we refer to generally refers to array type and object type data. Vue internally hijacks the properties of an object through the Object.defineProperty method, and the array is implemented by overriding the array method. Let's simply implement it below.

First, we define the data that needs to be intercepted.

const vm = new Vue({
 data () {
  return {
   count: 0,
   person: { name: 'xxx' },
   arr: [1, 2, 3]
  }
 }
})
let arrayMethods
function Vue (options) { // Only consider the operation of data here let data = options.data
 if (data) {
  data = this._data = typeof data === 'function' ? data.call(this) : data
 }
 observer (data)
}
function observer(data) { 
 if (typeof data !== 'object' || data === null) {
  return data
 }
 if (data.__ob__) { // The existence of the __ob__ attribute indicates that it has been intercepted return data
 }
 new Observer(data)
}

Please continue reading below for the implementation and function of arrayMethods, Observer, and __ob__

Implementing the Observer Class

class Observer {
 constructor (data) {
  Object.defineProperty(data, '__ob__', { // Define the __ob__ property on data, which is needed in array hijacking enumerable: false, // Not enumerable configurable: false, // Not configurable value: this // The value is the Observer instance })
  if (Array.isArray(data)) { //Intercept the array data.__proto__ = arrayMethods //Prototype inheritance this.observerArray(data)
  } else { // Object interception this.walk(data)
  }
 }
 walk (data) {
  const keys = Object.keys(data)
  for(let i = 0; i < keys.length; i++) {
   const key = keys[i]
   defineReactive(data, key, data[key])
  }
 }
 observerArray (data) { // intercept each item in the array data.forEach(value => observer(value))
 }
}

Object interception

A few points to note about object hijacking:

  • Traverse the object. If the value is still an object type, you need to call the observer method again.
  • If the new value set is an object type, it also needs to be intercepted
//Intercept function of processing object defineReactive(data, key, value) {
 observer(value) // If value is still an object type, you need to recursively hijack Object.defineProperty(data, key, {
  get() {
   return value
  },
  set(newValue){
   if (newValue === value) return
   value = newValue
   observer(newValue) // If the newValue value is also an object type, it needs to be hijacked}
 })
}

Array hijacking

A few points to note about array hijacking:

  • Arrays use the idea of ​​function hijacking (slice programming) to intercept data
  • Newly added values ​​in the array, if they are object types, also need to be re-intercepted
const oldArrayPrototype = Array.prototype
arrayMethods = Object.create(oldArrayPrototype)
const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] // Methods that can change the original array methods.forEach(method => {
 arrayMethods[methods] = function (...args) {
  const result = oldArrayPrototype[methods].call(this, ...args)
  const ob = this.__ob__ // this is the array that calls the method let inserted; // The collection of newly added items in the array needs to be intercepted switch(methods) {
   case 'push': 
   case 'unshift':
    inserted = args
   case 'splice':
    inserted = args.slice(2) // Because the second parameter of splice is the one that is added}
  if (inserted) {
   ob.observerArray(inserted)
  }
  return result
 }
})

Principle Summary

In the interview, if we need to hand-write the responsiveness principle of Vue, the above code is enough. However, by learning the source code of Vue, if we can give the following summary answers in the interview, we will be more favored by the interviewer.

The responsive principle of Vue 2.0 source code:

  • Because objects are intercepted recursively, the deeper the data level, the worse the performance.
  • Arrays are not intercepted using Object.defineProperty because performance will be poor if there are too many array items.
  • Only the data defined in data will be intercepted. The attributes we add later on the instance through vm.newObj = 'xxx' will not be intercepted.
  • Changing the index and length of the array will not be intercepted, so it will not cause the view to update.
  • If you need to intercept the addition of new attributes to data and the change of array index and length, you can use the $set method
  • You can use the Object.freeze method to optimize data and improve performance. The data using this method will not be rewritten by the set and get methods.

Vue 3.0 source code responsive principle:

  • In version 3.0, proxy is used instead of Object.defineProperty. It has 13 interception methods. It does not need to process objects and arrays separately, nor does it need to intercept recursively. This is also the biggest performance improvement.
  • Simple implementation of the responsive principle of Vue 3.0 version
const handler = {
 get (target, key) {
  if (typeof target[key] === 'object' && target[key] !== null) {
   return new Proxy(target[key], handler)
  }
  return Reflect.get(target, key)
 },
 set (target, key, value) {
  if(key === 'length') return true
  console.log('update')
  return Reflect.set(target, key, value)
 }
}
const obj = {
 arr: [1, 2, 3],
 count: { num: 1 }
}
// obj is the target object of the proxy, handler is the configuration object const proxy = new Proxy(obj, handler)

This is the end of this article on the detailed explanation of the data responsiveness principle of Vue. For more relevant Vue data responsiveness content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of the array of Vue data responsiveness principle
  • In-depth understanding of Vue's data responsiveness
  • Vue data responsiveness summary
  • Summary of knowledge points about Vue data responsiveness principle
  • How is Vue data responsiveness implemented?
  • A brief discussion on the principle of Vue data responsiveness
  • Vue explains the principle of data responsiveness in depth

<<:  Docker learning method steps to build ActiveMQ message service

>>:  MySQL 5.7.16 installation and configuration method graphic tutorial (Ubuntu 16.04)

Recommend

How to preview pdf file using pdfjs in vue

Table of contents Preface think Library directory...

Detailed explanation of Mysql function call optimization

Table of contents Function call optimization Func...

Vue implements horizontal beveled bar chart

This article shares the specific code of Vue to i...

Code for implementing simple arrow icon using div+CSS in HTML

In web design, we often use arrows as decoration ...

Mysql anonymous login cannot create a database problem solution

Frequently asked questions Access denied for user...

HTML input box optimization to improve user experience and ease of use

In order to improve user experience and ease of us...

How to automatically number the results of MYSQL query data

Preface In fact, I have never encountered this ki...

Linux five-step build kernel tree

Table of contents 0. The kernel tree that comes w...

The principle and basic use of Vue.use() in Vue

Table of contents Preface 1. Understanding with e...

HTML line spacing setting methods and problems

To set the line spacing of <p></p>, us...

A brief analysis of how to upgrade PHP 5.4 to 5.6 in CentOS 7

1. Check the PHP version after entering the termi...

MySQL Error 1290 (HY000) Solution

I struggled with a problem for a long time and re...

SQL implementation of LeetCode (197. Rising temperature)

[LeetCode] 197.Rising Temperature Given a Weather...

Example of how to generate random numbers and concatenate strings in MySQL

This article uses an example to describe how MySQ...