Home  >  Article  >  Web Front-end  >  A brief discussion on Vue responsiveness (array mutation method)

A brief discussion on Vue responsiveness (array mutation method)

不言
不言Original
2018-05-07 14:46:061595browse

This article mainly introduces a brief discussion about Vue responsiveness (array mutation method), which has certain reference value. Now I share it with you. Friends in need can refer to it

Preface

Many students who are new to using Vue will find that when changing the value of the array, the value does change, but the view is indifferent. Sure enough, it is because the array is too cool. ?

After checking the official documents, I discovered that it’s not that the goddess is too cold, but that you didn’t use the right method.

It seems that if you want the goddess to move by herself, the key is to use the right method. Although the method has been given in the official document, I am really curious. If you want to unlock more postures, you must first get into the heart of the goddess, so I came up with the idea of ​​exploring the responsive principle of Vue. (If you are willing to peel off my heart layer by layer. You will find that you will be surprised... I am addicted to the howling of ghosts and can't extricate myself QAQ).

Front tip, Vue’s responsiveness principle mainly uses ES5’s Object.defineProperty. Uninformed students can view relevant information.

Why does the array not respond?

If you think about it carefully, Vue's response is based on Object.definePropery. This method mainly modifies the description of the object's properties. Arrays are actually objects, and by defining the properties of the array, we should be able to produce responsive effects. Test your idea first, roll up your sleeves and get started.

const arr = [1,2,3];

let val = arr[0];

Object.defineProperty(arr,'0',{
  enumerable: true,
  configurable: true,
  get(){
    doSomething();
    return val;
  },
  set(a){
    val = a;
    doSomething();
  }
});

function doSomething() {

}

Then enter arr, arr[0] = 2, arr respectively in the console, you can see the results as shown below.

Hey, everything is as expected.

Next, after seeing this code, some students may have questions, why don’t this[0] be returned directly in the get() method? But should we use val to return the value? Think about it carefully, damn! ! ! It's almost an infinite loop. Think about it, get() itself is to get the value of the current attribute. Isn't calling this[0] in get() equivalent to calling the get() method again? It's so scary, so scary, it scares the laborers to death.

Although the goddess in your imagination may have this posture, the goddess in front of you is indeed not in this posture. How can a person like me, who has obvious attributes of a loser, guess the goddess? thought? Why not respond to data like this? Perhaps because arrays and objects are still different, defining the properties of arrays may cause some troubles and bugs. Or it may be because a large amount of data may be generated during the interaction process, resulting in overall performance degradation. It is also possible that the author can use other methods to achieve the effect of data response after weighing the pros and cons. Anyway, I can't figure it out.

Why can I respond by calling the native method of the array?

Why can the data respond by using these array methods? Let’s take a look at the source code of the array part first.

Simply speaking, the function of def is to redefine the value of the object attribute.

//array.js
import { def } from '../util/index'

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
//arrayMethods是对数组的原型对象的拷贝,
//在之后会将该对象里的特定方法进行变异后替换正常的数组原型对象
/**
 * Intercept mutating methods and emit events
 */
[
 'push',
 'pop',
 'shift',
 'unshift',
 'splice',
 'sort',
 'reverse'
]
.forEach(function (method) {
 // cache original method
 //将上面的方法保存到original中
 const original = arrayProto[method]
 def(arrayMethods, method, function mutator (...args) {
  const result = original.apply(this, args)
  const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // notify change
  ob.dep.notify()
  return result
 })
})

Post the def part of the code

/**
 * Define a property.
 */
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
 Object.defineProperty(obj, key, {
  value: val,
  enumerable: !!enumerable,
  writable: true,
  configurable: true
 })
}

Array.js mutates some methods of arrays. Let's take the push method as an example. The first thing is to use original = arrayProto['push'] to save the native push method.

Then we need to define the mutation method. For the def function, if we don’t go into details, def(arrayMethods,method,function(){}), this function can be roughly expressed as arrayMethods[method ] = function mutator(){};

Assuming that the push method is called later, the mutator method is actually called. In the mutator method, the first thing is to call the original that saves the original push method. Find the actual value. A bunch of text looks really abstract, so write a low-profile version of the code to express the meaning of the source code.

const push = Array.prototype.push;

Array.prototype.push = function mutator (...arg){
  const result = push.apply(this,arg);
  doSomething();
  return result
}

function doSomething(){
  console.log('do something');
}

const arr = [];
arr.push(1);
arr.push(2);
arr.push(3);

The result viewed in the console is:.

Then the code

const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // notify change
  ob.dep.notify()

in the source code corresponds to doSomething()

In this code, the two-word comment notify change is clearly written. If you don’t know these two words, just search them on Baidu. I will do it for you here. , these two words mean to publish changes! Each time this method is called, the value will be calculated, and then some other things will be done, such as publishing changes and observing new elements. The other processes of response will not be discussed in this article.

[
 'push',
 'pop',
 'shift',
 'unshift',
 'splice',
 'sort',
 'reverse'
]

There are so many methods at present. As long as you use the right method, you can change the posture of the goddess!

Summary

As for the title, I changed it again and again. At first it was called A Brief Analysis of Vue Response Principles, but then I saw that the title was too big. Let’s start with the simplest one, start with arrays, and this article won’t take too much time to read. If there is any mistake in this article that may mislead others, please point it out. I would be very grateful.

Related recommendations:

A brief discussion on the principle of Vue data responsiveness


##

The above is the detailed content of A brief discussion on Vue responsiveness (array mutation method). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn