An overview of the
The purpose of reactive data is to be able to run functions spontaneously when data, object properties, or an array item changes. The most common thing in VUE is to rerun the render function to refresh the page when data changes.
Implementing responsiveness in VUE relies on a few core components
- Observer
- Dep
- Watcher
- Scheduler
Observer
The Observer is designed to do a simple job of turning ordinary data into responsive data
- For objects: hijacking objects is done by recursively calling Object.defineProperty, adding getters and setters for each property so that vUE can be notified to do something when a property is requested or changed. But even then we can’t listen for additions and deletions of object attributes, so vue does
$set
和$delete
Instance method to add or subtract attributes from reactive data - In the case of arrays, Vue changes the implicit prototype of the Array to a vUE custom object, overriding some of the original methods that alter the Array so that Vue can listen for changes in the Array’s contents, and finally pointing the implicit prototype of the custom object to array. prototype
Graph LR (Array) - __proto__ -- > B (vue custom object) - B __proto__ - > C (Array. The protoType)
Dep
At this point the data has become responsive data but we have no idea what to do when we read the property, when we modify the property. And the Dep is the vUE that does this. The VUE generates a Dep instance for each responsive data, and the Dep instance does two things
- Logging dependencies: When someone accesses this data, it is logged
- Distribute updates: Notify all dependencies of changes when data is modified
Graph LR A(getter) -- record dependency --> B(someone use me) C(setter) -->D(I have been changed)
Wather
Now we know that Dep logs dependencies when accessing a response data, but how does the Dep know who actually accessed me
Watcher was designed to solve this problem
When a function runs with response data, Dep has no way of knowing which function is using it, so we hand this function over to Watcher to execute. Watcher sets a global variable to record the current execution of the Watcher. When a Dep logging dependency occurs, the Dep records this global variable, indicating that the current Watcher is using itself. When data changes and Dep sends out an update, Watcher will be notified that I have changed, and Watcher will call the corresponding function again
Every Vue instance has at least one Watcher instance to hold the render function, which Watcher calls to collect dependencies when a Vue component is first rendered
All reactive data used in render will record this Watcher
When the data changes, Dep notifying Watcher and Wather rerunks the Render function to update the dependency.
Scheduler
At this point, vUE responsiveness is almost complete, but there are still some problems.
When Render uses a lot of reactive data, if the reactive data changes, the Watcher for recording render will be called multiple times, wasting a lot of performance. This is clearly unreasonable.
Instead of executing immediately, Watcher actually assigns itself to the Scheduler, which maintains a queue in which the same Watcher can only exist once. Vue provides nextTick methods internally. You can put these watchers into microqueues in an event loop, so the execution of the Watcher is asynchronous