Vue listening array change source code parsing, vue listening array source code

Source: Internet
Author: User

Vue listening array change source code parsing, vue listening array source code

In the previous code, the processing of arrays is ignored, and only the content that needs to be concerned is concerned. The pretend array does not exist.

This article begins to consider the array issue.

Start with the simplest

First, let's take a look at the question: how can we monitor object changes in the array? Ignore the array itself and its general values, and only consider the objects in the object array.

Traverse the array, and then call the observe method for each object in the array.

// The code that has not been rewritten in the previous article. var Observer = function Observer (value) {this. value = value; this. dep = new Dep (); // if it is an Array, all elements are traversed if (Array. isArray (value) {this. observeArray (value);} else {this. walk (value) ;}}; Observer. prototype. observeArray = function observeArray (items) {// traverses all elements of the array and binds a single element to getter and setter for (var I = 0, l = items. length; I <l; I ++) {observe (items [I]) ;}};

Realistic requirements

The actual implementation is certainly not as simple as the above example. The Listener array is described in the official documentation as follows:

Vue contains a set of mutation methods for observing arrays, so they also trigger view update. These methods are as follows:
Push (), pop (), shift (), unshift (), splice (), sort (), reverse ()

Due to Javascript restrictions, Vue cannot detect the following changed Arrays:

When you directly set an index for an item, for example: vm. items [indexOfItem] = newValue
When you modify the length of an array, for example, vm. items. length = newLength
Therefore, you need to listen to some methods of the array itself.

A small function that is frequently used

Def, which appears repeatedly throughout the Vue source code. You can use Object. defineProperty () to define the property key on obj (or modify the existing property key ):

Function def (obj, key, val, enumerable) {Object. defineProperty (obj, key, {value: val, // convert it to the boole value. If no parameter is passed, convert it to false enumerable :!! Enumerable, writable: true, retriable: true });}

Add a group of methods to an object

Add a group of methods to the object. If the environment in which the object is located supports proto, it is easy to direct the object's proto to this group of methods. If not, traverse this group of methods and add them to the object in sequence as hidden attributes (that is, enumerable: false, cannot be found by the in keyword ):

var hasProto = '__proto__' in {};var augment = hasProto ? protoAugment : copyAugment;function protoAugment(target, src) {  target.__proto__ = src;}function copyAugment(target, src, keys) {  for(var i = 0; i < keys.length; i++) {    var key = keys[i];    def(target, key, src[key]);  }}

Let's get started with a simple

Var arrayPush ={}; (function (method) {var original = Array. prototype [method]; arrayPush [method] = function () {// this point can be seen through the following test console. log (this); return original. apply (this, arguments) };} ('push ');
Var testPush = []; testPush. _ proto _ = arrayPush; // The output shows that this points to testPush // [] testPush. push (1); // [1] testPush. push (2 );

Pseudo-Rewrite array prototype to listen for Array changes

As stated in the official document, only push (), pop (), shift (), unshift (), splice (), sort (), and reverse () methods need to be monitored, these seven methods can be divided into two types:

1. The push (), unshift (), and splice () methods may add new elements to the array;

2. Other methods that do not add elements.

To avoid Global Array contamination, create a new Array. prototype is the prototype object, and then adds the new object as the prototype or attribute to the value of the Observer to monitor its changes.

var arrayProto = Array.prototype;var arrayMethods = Object.create(arrayProto);

Next, traverse several methods that need to trigger the update and attach them to arrayMethods in sequence:

['Push', 'pop', 'shift ', 'unshift', 'splice ', 'sort', 'reverse']. forEach (function (method) {// obtain the original array operation method var original = arrayProto [method]; // create an attribute method on arrayMethods and specify a value for the method (function) // rewrite the array method def (arrayMethods, method, function mutator () {var arguments $1 = arguments; var I = arguments. length; var args = new Array (I); // convert the pseudo Array arguments to the Array format // Why not use []. slice. call (argume )? While (I --) {args [I] = arguments $1 [I];} var result = original. apply (this, args); // because arrayMethods is used as a prototype of values in the Observer or directly as an attribute, this here generally points to values in the Observer // Of course, you also need to modify the Observer so that the value has an attribute pointing to the Observer itself, __ob __, to associate the two with var ob = this. _ ob __; // store the newly added array element var inserted; // for several methods that may have new elements, consider switch (method) {case 'push' separately ': inserted = args; break; case 'unshift': inserted = args; break; case 'splice ': // The third parameter of the splice method is the new element inserted = args. slice (2); break;} if (inserted) {// bind the getter and setter to the newly added elements to ob. observerArray (inserted);} // trigger method ob. dep. Y (); return result;}) ;}; var arrayKeys = Object. getOwnPropertyNames (arrayMethods );

Update Observer

Rewrite the Observer according to the comments in the code above to associate the two to listen for Array changes:

Var Observer = function Observer (value) {this. value = value; this. dep = new Dep (); def (value, '_ ob _', this); // if it is an Array, all elements are traversed if (Array. isArray (value) {var argument = hasProto? ProtoAugment: copyAugment; argument (value, arrayMethods, arrayKeys); this. observeArray (value) ;}else {this. walk (value );}};

References:
Vue early source code Learning Series II: How to monitor changes in an array

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.