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

Vue implements login verification code

This article example shares the specific code of ...

Ten important questions for learning the basics of Javascript

Table of contents 1. What is Javascript? 2. What ...

React implements a general skeleton screen component example

Table of contents What is a skeleton screen? Demo...

More Features of the JavaScript Console

Table of contents Overview console.log console.in...

A detailed introduction to the CSS naming specification BEM from QQtabBar

BEM from QQtabBar First of all, what does BEM mea...

Independent implementation of nginx container configuration file

Create a container [root@server1 ~]# docker run -...

How to use MySQL 5.7 temporary tablespace to avoid pitfalls

Introduction MySQL 5.7 aims to be the most secure...

Example code of vue custom component to implement v-model two-way binding data

In the project, you will encounter custom public ...

Detailed explanation of the usage of Object.assign() in ES6

Table of contents 2. Purpose 2.1 Adding propertie...

Introduction to 10 Hooks in React

Table of contents What is ReactHook? React curren...

Detailed explanation of the basic use of Apache POI

Table of contents Basic Introduction Getting Star...

Basic learning and experience sharing of MySQL transactions

A transaction is a logical group of operations. E...