The opening

Recently in the study of Vue source code, read some online blogs, it seems to feel very difficult. Record their own learning understanding, hope to be able to achieve simple and easy to understand, do not look at the source code can understand the effect 😆

If there is a mistake, implore big guy to give directions hey 😋

Object.defineProperty

I believe that many students more or less understand the Vue response principle is realized by Object. DefineProperty. Objects bound by object.defineProperty become “responsive”. That is, when you change this object, it fires get and set events. This in turn triggers some view updates. For example, 🌰

function defineReactive (obj, key, val) {
    Object.defineProperty(obj, key, {
        enumerable: true.configurable: true.get: (a)= > {
            console.log('I've been read, should I do something? ');
            return val;
        },
        set: newVal= > {
            if (val === newVal) {
                return;
            }
            val = newVal;
            console.log("The data has changed, I need to render the new value to the page!"); }})}let data = {
    text: 'hello world'};// Bind the text property on data
defineReactive(data, 'text', data.text);

console.log(data.text); // Console output < I was read, should I do something good? >
data.text = 'hello Vue'; // The console output 
      
Copy the code

Observer “Responsive”

Vue uses the Observer class to manage the process of instantiating the Object.defineProperty as described above. This can be described as a “responsive” binding of this.data, which is the data property we defined in the Vue code.

class Observer {
    constructor() {
        // Bind data through method responsively
    	observe(this.data); }}export function observe (data) {
    const keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
       // Bind each property we define in data in a responsive waydefineReactive(obj, keys[i]); }}Copy the code

Dep “Dependency Management”

What is dependence?

I believe that have not seen the source code or just contact with the word Dep classmates will be more meng. So what is the Dep for? How do we handle notifying the view to be updated, even though we can listen for changes to the data after we’ve responded to it with defineReactive?

Dep is to help us collect [exactly where to notify]. For example, in the following code case, we find that although there are text and message properties in data, only Message is rendered to the page, and no change in text will affect the display of the view, so we only collect message to avoid some useless work.

In this case, the Message Dep collects a dependency that is used to manage message changes in data.

<div>
    <p>{{message}}</p>
</div>
Copy the code
data: {
    text: 'hello world'.message: 'hello vue',}Copy the code

When using the watch property, it is the developer’s custom to listen for changes to properties in a data. For example, to listen for changes in the message, we need to notify the watch hook when the message changes, and let it perform the callback function.

At this point, the Message Dep collects two dependencies, the second of which is used to manage message changes in the Watch.

watch: {
    message: function (val, oldVal) {
        console.log('new: %s, old: %s', val, oldVal)
    },
}        
Copy the code

When a developer defines a computed computing attribute, the following messageT attribute depends on message. Therefore, we also notify computed when message changes and have it perform the callback function. At this point, the MESSAGE Dep collects three dependencies that are used to manage message changes on computed.

computed: {
    messageT() {
        return this.message + '! '; }}Copy the code

An attribute may have multiple dependencies, and each responsive data has a Dep to manage its dependencies.

How to collect dependencies

How do we know that a property in the data is being used? The answer is object.defineProperty, because reading a property triggers the GET method. The code can be modified as follows:

function defineReactive (obj, key, val) {
    let Dep; / / rely on

    Object.defineProperty(obj, key, {
        enumerable: true.configurable: true.get: (a)= > {
            console.log('I've been read, should I do something? ');
            // The dependency is read, and the dependency is collected
            Dep.depend(); // Add this time
            return val;
        },
        set: newVal= > {
            if (val === newVal) {
                return;
            }
            val = newVal;
            // Has been changed, notify the dependency to update
            Dep.notify(); // Add this time
            console.log("The data has changed, I need to render the new value to the page!"); }})}Copy the code

What is dependence

So what exactly is dependence? The answer is revealed in the figure above, which is Watcher.

Watcher “intermediary”

A Watcher is a mediation-like role. For example, a message has three mediations. When the Message changes, the three mediations are notified, and they perform the required changes.

Watcher can control whether it is a property in Data, watch, or computed. Watcher has its own uniform update entry, and when you tell it, it executes the corresponding update method.

So we can infer that Watcher must have two methods. One is to notify changes, and the other is to be collected into the Dep.

class Watcher {
    addDep() {
        // This Watcher is going to be stuck in the Dep
    },
    update() {
        // Dep informs me of the update ~~}},Copy the code

conclusion

To review, the core Vue responsive principles are the Observer, Dep, and Watcher.

When the data is read, the GET method is triggered and the Dep is performed to collect the dependencies, i.e. the Watcher.

When data is changed, the set method is triggered to perform the update through all of the corresponding dependencies (Watcher). For example, Watch and Computed execute developer custom callback methods.

This article is a primer for a simple understanding of the roles and relationships of Observer, Dep, and Watcher. The following will gradually detailed and in-depth, step by step understanding and learning.

If you think it helps you, just give it a like

A series in writing

  • 1. Vue responsive Principles – Understand Observer, Dep, Watcher
  • 2. Reactive Principle – How to listen for Array changes
  • 3. Reactive Principle – How to listen for Array changes? A detailed version
  • 4. Vue asynchronous update – nextTick Why microtask first?

Welcome to the Github blog