Implement a simple data response system

Implement a simple data response system

1. Dep

In fact, this is a container for dependency collection. depend collects dependencies, and notify triggers dependencies.

class Dep{
  constructor() {
    this._subs = [];
  }
  depend() {
    this._subs.push(Dep.target)
  }
  notify() {
    this._subs.forEach(item => {
      item.fn();
    })
  }
}

// Actually, this is the beginning of the love between dep and watcher. // A global property is used in watcher to store watcher
Dep.target = null;

function pushTarget(watch) {
  Dep.target = watch;
}

function popTarget() {
  Dep.target = null;
}

2. Understand obverser

Recursively convert all properties of the data object into accessor properties

// Convert to accessor property function defineReactive (obj, key, val, shallow) {

  // Create a dependency collection container let dep = new Dep();
  let childOb = !shallow && observe(val)

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      if(Dep.target) {
        // Collect dependencies dep.depend();
      }
      return val;
      // ...
    },
    set: function reactiveSetter (newVal) {
      if(newVal === val) return;
      // Continue recursively traversing observe(newVal);
      //Trigger dependency dep.notify();
      // ...
    }
  })
}

class Observer{
  constructor(data) {
    this.walk(data);
  }

  walk(data) {
    const keys = Object.keys(data)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(data, keys[i], data[keys[i]])
    }
  }
}

// Recursively convert all properties of the data object into accessor properties function observe (data) {
  if(Object.prototype.toString.call(data) !== '[object Object]') return;
  new Observer(data);
}

At this point, you can convert all properties of any object into accessors

3. Understand watch and observer

const data = {
  a: 1,
  b: 2
}

//First monitor an object observe(data);

The main function of watcher is to detect a certain attribute and trigger a callback when the attribute changes.

class Watcher{
  /**
  * @params {Function} exp a property expression * @params {Function} fn callback */
  constructor(exp, fn) {
    this.exp = exp;
    this.fn = fn;

    //Save watcher
    // Dep.target = this;
    pushTarget(this);

    // Execute the expression function once first, and in the calling process,
    // Trigger the accessor of data.a, and the get of data.a is executed.
    // Trigger dep.depend() to start collecting dependencies this.exp();

    // Release Dep.target
    popTarget();
  }
}

// new Watcher Such a dependency is collected new Watcher(() => {
  return data.a + data.b;
}, () => {
  console.log('change')
})

4. Trigger Dependency

data.a = 3; // change
data.b = 3; // change

5. Summarize the process

  • Convert all properties of an object into accessors
  • When adding watcher to a property, get function of the property will be triggered. The watcher will be stored in the dep dependency container of the property in the get function.
  • When this property changes, the set method of the property will be triggered. set function will execute all the dependencies stored in dep

This is the end of this article about implementing a simple data response system. For more relevant data response system content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Use of data response system for Vue source code analysis

<<:  Introduction to the use of common Dockerfile commands

>>:  How to control the proportion of Flex child elements on the main axis

Recommend

Summary of Docker Data Storage

Before reading this article, I hope you have a ba...

MySQL database Load Data multiple uses

Table of contents Multiple uses of MySQL Load Dat...

Detailed explanation of vue-router 4 usage examples

Table of contents 1. Install and create an instan...

MySQL query tree structure method

Table of contents MySQL query tree structure 1. A...

Vuex modularization and namespaced example demonstration

1. Purpose: Make the code easier to maintain and ...

Detailed explanation of mysql integrity constraints example

This article describes the MySQL integrity constr...

Install CentOS 7 on VMware14 Graphic Tutorial

Introduction to CentOS CentOS is an enterprise-cl...

Sharing experience on the priority of CSS style loading

During the project development yesterday, I encoun...

js to implement collision detection

This article example shares the specific code of ...

How to connect to virtual machine MySQL using VScode in window environment

1. Virtual Machine Side 1. Find the mysql configu...

8 tips for Vue that you will learn after reading it

1. Always use :key in v-for Using the key attribu...

Complete steps for deploying confluence with docker

Confluence is paid, but it can be cracked for use...