preface

Although this article is a simple exercise in the hijacking of array archetypes, to fully understand why it is done, you should have some understanding of vUE responsive dependency collection. For those who don’t understand, you can look at the 298 lines of code here to understand the Vue responsive principle and next-tick principle, and finally write a small demo of your own

I suggest you write code and understand as you watch.

1.AOP

Vue hijacks objects through the Object.defineProperty method. The Array is handled through the idea of section-oriented programming, cutting a knife between the prototype method of the user calling Array and the prototype method. In the middle of the cut, the Array dependency trace is realized. For those of you who are familiar with this concept, let’s draw a diagram for those of you who are not familiar with this concept.

To a figure

Just like middleware, each time the user uses Array’s methods, the slicing function cannot be bypassing. After the slicing function is processed, the corresponding prototype function will be called and returned based on the user’s input. The slice function is invisible in user mode.

2. Implement slice

Talk is Cheep, let’s go to the code

// The array to be hijacked
let arr = [1.2.3];

// If you want to hijack the prototype, you need to take it first
let arrayProto = Array.prototype;
// Create our own prototype method
let arrayMethods = Object.create(Array.prototype);
// For example, we want to hijack the push method on the prototype
arrayMethods.push = function(. args){
    // First call the real prototype method to get the normal return value
    const result = arrayProto.push.apply(this,args)
    // After the normal push, insert our sliced logic code
    console.log('Push method is being heard')
    // Returns the normal return value
    return result
}

arr.__proto__ = arrayMethods

console.log(arr.push(4))
Copy the code

Console output after run



As you can see, our slicing code has been successfully executed, andThere is no impact on the original method.

Should we slice all the methods in the array prototype at once? The answer is clearly no.

Vue slices array methods so that they can be used for dependency collection. Specifically, it wants to know when the array data has changed and render the view. In this case, we only need to slice up the prototype methods that can change the array data.

Slice up any prototype methods that can alter array data

// array to be hijacked let arr = [1,2,3]; Let methods = ['push', 'pop', 'shift', 'unshift', 'reverse', 'sort', 'splice'] Let arrayProto = array.prototype; ArrayMethods = object.create (array.prototype); ArrayMethods [method] = function (arrayMethods[method] = function (... Const result = arrayProto[method]. Apply (this,args) // Insert slice console.log(' called ${method} method ') Return result}}) arr.__proto__ = arrayMethods console.log(arr.push(4)) console.log(arr.splice(0,1))Copy the code

Run output



That’s it. We’ve beenIn the premise of not affecting the original function to change the array value of the method to slice.

Based on this capability, we made a small simulation of VUE, with as little code as possible.

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <button id="button">push</button>
</body>
<script>
    let list = [1.2.3]
    let i = 4;
    // List the methods to hijack
    let methods = [
        'push'.'pop'.'shift'.'unshift'.'reverse'.'sort'.'splice'
    ]

    // If you want to hijack the prototype, you need to take it first
    let arrayProto = Array.prototype;
    // Create our own prototype method
    let arrayMethods = Object.create(Array.prototype);

    // the traversal method
    methods.forEach(method= >{
        // Slice each method
        arrayMethods[method] = function (. args){
            // Call the real prototype method first to get the normal return value
            const result = arrayProto[method].apply(this,args)
            // The data has changed and we want to notify the view of the update
            console.log(` calls${method}Methods `)
            update()
            
            return result
        }
    })

    // Change the list prototype
    list.__proto__ = arrayMethods

    // Simulate update view
    function update(){
        document.getElementById('app').innerHTML = `${list}`
    }

    // Simulate user business code to change data
    function clickFn(){
        list.push(i);
        i++
    }
    document.getElementById('button').addEventListener('click',clickFn)

    // The data has not been modified at the beginning, the first time is a render view
    update()
</script>
</html>
Copy the code

The page is simple, but the effect is amazing. Click the button to simulate the user’s manipulation of the data, but the latest data is automatically updated to the view.

summary

Vue2. X does not listen for subscript updates to arrays because it is slicing array methods.

The author is very dish, can bring you some harvest is very happy, can’t if also hope to mouth mercy.