Home > Web Front-end > JS Tutorial > body text

Why can't Vue detect array changes? The reasons are as follows

php是最好的语言
Release: 2018-07-27 14:42:37
Original
13834 people have browsed it

Problem description: Vue detects data changes through Object.defineProperty, so it is understandable that it cannot monitor the addition operation of the array, because this detection and binding operation has been done for all properties in the constructor.

But the official text: Due to JavaScript limitations, Vue cannot detect the following changed arrays:

When you use the index to directly set an item, for example: vm.items[indexOfItem] = newValue
When you modify the length of the array, for example: vm.items.length = newLength

What does this sentence mean? I tested that Object.defineProperty can set the accessor property of the property through the index property, so why can't it be monitored?

Some people on the forum said that because the length of the array is variable, even if the length is 5, it may not have index 4. I would like to ask where this answer comes from. If the length is modified, the new elements will be is added to the end, its value is undefined, and their values ​​can be obtained through the index. Why is it called "may not have index 4"?

Now that we know the length of the array, why can't we traverse all the elements and add set and get through the index attribute? Can we update the view at the same time?

If I have to say, considering the performance issue, assuming that the element content only has 4 meaningful values, but the length is indeed 1000, it is impossible for us to perform detection operations for 1000 elements. But the official said it is due to JS limitations. I want to know what this limitation is? Thank you very much for helping me solve this problem.



Faced with this problem, what I want to say is, first of all, an array with a length of 1000 but only 4 elements is not necessarily It will affect performance, Because in addition to the for loop, the traversal of data in js also includes forEach, map, filter, some, etc., except for the for loop (for, for...of), other traversals are all about key values. Traversal, that is, the vacancies other than those four elements will not be traversed, so there will be no performance loss. Because if there are no operations in the loop body, the performance impact will be negligible, as follows It is the result of traversing an array with a length of 10000 but only two elements using for and forEach respectively:

var arr = [1]; arr[10000] = 1
function a(){
    console.time()
    for(var i = 0;i<arr.length;i++)console.log(1)
    console.timeEnd()
}
a(); //default: 567.1669921875ms
a(); //default: 566.2451171875ms

function b(){
    console.time()
    arr.forEach(item=>{console.log(2)})
    console.timeEnd()
}
b(); //default: 0.81982421875ms
b(); //default: 0.434814453125ms
Copy after login

You can see that the result is very obvious, but if no operation is performed in the for loop, the speed of the two is about the same

Secondly, what I want to say is that I don’t know what this limit is    (⇀‸↼‶)  ( •́ω•̀ )╭

The Object.defineProperty() method will be directly Defines a new property on an object, or modifies an existing property of an object, and returns the object. The index of the array is also an attribute, so we can monitor changes in the array elements

var arr = [1,2,3,4]
arr.forEach((item,index)=>{
    Object.defineProperty(arr,index,{
        set:function(val){
            console.log(&#39;set&#39;)
            item = val
        },
        get:function(val){
            console.log(&#39;get&#39;)
            return item
        }
    })
})
arr[1]; // get  2
arr[1] = 1; // set  1
Copy after login

But if we add an element, the listening event will not be triggered, because we are not monitoring this new attribute. Delete an attribute. Too.

Back to the main question, since arrays can be monitored, why can’t vue detect changes in array elements caused by vm.items[indexOfItem] = newValue, even if this Does the element corresponding to the subscript exist and is monitored?

In order to clarify this problem, I tested it with the source code of vue. The following is the source code of vue for data monitoring:
Why cant Vue detect array changes? The reasons are as follows

You can see that when the data is an array When the data is an array, it will stop monitoring the data attributes. Let's modify the source code:
Why cant Vue detect array changes? The reasons are as follows

When the data is an array, its attributes will still be monitored, and then print something in the get and set in the defineReactive function. , so that we know that get and set are called. A simple judgment is added here, just look at the get of the array elements, set
Why cant Vue detect array changes? The reasons are as follows

and then write a simple case, the main test is to use vm.items[indexOfItem] = newValueChange whether array elements can be monitored and render the page responsively
Why cant Vue detect array changes? The reasons are as follows

Run the page
Why cant Vue detect array changes? The reasons are as follows

You can see that it has been run 6 times get, the length of our array is 3, which means that the array is traversed twice. Not more than two times. When the page is rendered once, a data listening event may be triggered multiple times, even if the data is only used once. The specific details need to be determined by how you write the code. Take this for example, when the monitored data is an array, the dependArray function will be run (the code is in the implementation of get in the picture above). In this function, the array is traversed and the value is obtained, so there will be three more times of get, here Mainly Vue's monitoring of the arr array in data triggers the dependArray function.

When we click on one of the elements, for example, I clicked on 3
Why cant Vue detect array changes? The reasons are as follows

You can see that set will be run first, then the data will be updated, the page will be re-rendered, and the array will be traversed twice.

but! ! ! The array has indeed become responsive, which means that the js syntax function does not limit the monitoring of the array.

Here we are testing with an array of length 3. When I increase the length of the array to 9
Why cant Vue detect array changes? The reasons are as follows

you can see that 18 times of get are run, and the array It is still traversed twice. The same applies to clicking on an element. It is also traversed twice when rendering.
Why cant Vue detect array changes? The reasons are as follows

After the above experiment, I concluded that arrays can be updated responsively in vue, but I don’t understand why Youda didn’t add this feature because of his considerations. , I hope someone who knows will give me some advice

Related articles:

Array change detection problem in vue

Why is the json returned Cannot be converted to an array

Related videos:

Array change detection-Wheat Academy Vue.js video tutorial                                                          

The above is the detailed content of Why can't Vue detect array changes? The reasons are as follows. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!