Реактивность в Javascript

Spread the love

Что такое реактивность?

Это способность фрагмента кода автоматически обновляться или перерисовываться в ответ на изменения в данных, к которым он привязан.

Попробуем понять по проще ⏬

Initial State

Selling Price (Цена продажи) и Buying Price (цена покупки) – это две переменные состояния, от которых зависит значение Profit (прибыли).

Explanation

В случае реактивной системы

Переменная прибыли Profit будет обновляться при любых изменениях цены продажи Selling Price или цены покупки Buying Price.

В исходном состоянии цена продажи 500, а цена покупки 300, поэтому прибыль будет (500-300) = 200.

Когда мы обновляем Цену покупки до 100, Прибыль автоматически пересчитывается и обновляется до (500-100)=400.

В случае нереактивной системы

При любых изменениях Selling Price (цены продажи) или Buying Price (цены покупки) переменная прибыли не будет обновляться до тех пор, пока снова не будет вызвана функция calculateProfit().

Итак, в начальном состоянии цена продажи 500, а цена покупки 300, поэтому прибыль будет (500-300) = 200.

Когда мы обновляем цену покупки до 100, прибыль остается такой же, как и раньше. (500-300) = 200


🤔 Где используется понятие реактивности?

Концепция реактивности находится во ❤️ всех современных фронтенд фреймворках (React, Next.js, Vue.js и т. д.).

Некоторые важные части, где используется эта концепция и практика программирования:

  • Хук useState React.js
  • повторно визуализировать виджеты, когда какая-либо переменная ограниченного состояния была обновлена

🚀🚀 Начнем строить реактивную систему

Начните с простой нереактивной системы

let buyingPrice = 200
let sellingPrice = 500

let profit;

function calculateProfit(){
    profit = sellingPrice - buyingPrice
}

calculateProfit()
console.log("Profit : "+profit) // Profit : 300

// Update the selling price
buyingPrice = 100

// call calculateProfit() to recalculate
calculateProfit()
console.log("Profit : "+profit) // Profit : 400

Приступим к созданию реактивной системы

Шаг 1: Создайте класс зависимостей

Управляйте зависимостями, которые должны быть уведомлены, когда эти данные были обновлены или изменены.

class DependancyTracker{
    constructor(){
        this.subscribers = []
    }
    // Register the function of dependent code
    depend(){
        if(target && this.subscribers.includes(target) !== true){
            this.subscribers.push(target);
        }
    }
    // Notify the dependent codes to act on update of this data
    notify(){
        for (let i = 0; i < this.subscribers.length; i++) {
            let func = this.subscribers[i];
            func(); // run the function
        }
    }
}

Посмотрим, ee в действии

let track = new DependancyTracker();
let profit;
let buyingPrice = 200;
let sellingPrice = 400;

function calculateProfit(){
    profit = sellingPrice - buyingPrice
}

// Register the depndent code
target = calculateProfit
track.depend()
target()

// Initial profit 
console.log("Profit : "+profit) // Profit : 200

// Update the selling price
sellingPrice = 500

// Notify all the dependent codes for re-compute
track.notify(); 
// calculateProfit is also an part of the dependent codes.

console.log("Profit : "+profit) // Profit : 300

Шаг 2. Поиграем с геттером и сеттером

Словарь для хранения начальных значений

const data = {
    "buyingPrice" : 200
}

Давайте установим геттер и сеттер для указанного ключа

let internalvalue = data.buyingPrice;

Object.defineProperty(data, "buyingPrice", {
    get: function() {
        console.log("Get trigerred");
        return internalvalue;
    },
    set: function(val) {
        internalvalue = val;
        console.log("Set trigerred")
    }
})

Посмотрим, на это в действии

data.buyingPrice=900
console.log(data.buyingPrice)

Шаг 3: Создадим функцию watch, чтобы немного упростить процесс.

function watch(func){
    target = func;
    target();
    target = null;
}

Шаг 4: Заканчиваем!!!

const data = {
    "buyingPrice" : 200,
    "sellingPrice": 400
}

let target = null;

class DependancyTracker{
    constructor(){
        this.subscribers = []
    }
    depend(){
        if(target && this.subscribers.includes(target) !== true){
            this.subscribers.push(target);
        }
    }
    notify(){
        for (let i = 0; i < this.subscribers.length; i++) {
            this.subscribers[i]();
        }
    }
}

Object.keys(data).forEach(key => {
    let internal = data[key];
    let dep = new DependancyTracker()

    Object.defineProperty(data, key, {
        get: function() {
            dep.depend(); // link target function
            return internal;
        },
        set: function(val) {
            internal = val; // set value
            dep.notify(); // notify dependent variables linked funtion
        }
    })

})

// Watch function
function watch(func){
    target = func;
    target();
    target = null;
}

// Link calculateProfit function in watch
watch(() => {
    data.profit = data.sellingPrice - data.buyingPrice
})

console.log("Profit : "+data.profit) // Profit : 200

data.sellingPrice = 700
console.log("Profit : "+data.profit) // Profit : 500

data.sellingPrice = 900
console.log("Profit : "+data.profit) // Profit : 700

Завершение🎉🎉

Надеюсь из этой статьи, вы лучше поняли концепцию реактивности.


Перевод статьи: Reactivity in Javascript


Дополнительная информация:
Понимание реактивности во Vue.js (Шаг за Шагом)

Была ли вам полезна эта статья?
[2 / 5]

Spread the love
Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments