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

A brief introduction to VUE uni-app core knowledge

Table of contents specification a. The page file ...

Solution to the problem of adaptive height and width of css display table

Definition and Usage The display property specifi...

Detailed steps to build the TypeScript environment and deploy it to VSCode

Table of contents TypeScript environment construc...

Basic steps to use Mysql SSH tunnel connection

Preface For security reasons, the root user of My...

MySQL 5.7.17 installation and configuration method graphic tutorial under win7

I would like to share with you the graphic tutori...

Vue uses Baidu Maps to realize city positioning

This article shares the specific code of Vue usin...

A brief discussion on MySQL select optimization solution

Table of contents Examples from real life Slow qu...

Introduction to MySQL database performance optimization

Table of contents Why optimize? ? Where to start?...

Using JavaScript difference to implement a comparison tool

Preface At work, I need to count the materials su...

Introduction to MySQL role functions

Table of contents Preface: 1. Introduction to rol...

Summary of things to pay attention to in the footer of a web page

Lots of links You’ve no doubt seen a lot of sites ...

HTML Table Tag Tutorial (47): Nested Tables

<br />In the page, typesetting is achieved b...

Introduction to the deletion process of B-tree

In the previous article https://www.jb51.net/arti...