首頁  >  文章  >  web前端  >  使用 Javascript 從頭開始建立反應式商店

使用 Javascript 從頭開始建立反應式商店

DDD
DDD原創
2024-11-04 11:32:02987瀏覽

反應式程式設計是一種巧妙的方法,可讓您建立動態反映資料變更的應用程式。它是 React 和 Vue 等許多現代 JavaScript 框架背後的核心技術 - 它會根據用戶操作或其他狀態變化進行更新。理解反應性背後的內容可能感覺工作量太大,感覺就像框架所針對的「神奇」抽象之一。但是,如果您可以自己建立一個小型反應式系統來看看它是如何運作的呢?

本文將透過使用 JavaScript 從頭開始建立一個簡單的反應式儲存來介紹反應式程式設計的基礎知識。我們將以最小的實作方式介紹關鍵概念,包括依賴項追蹤和自動更新。最後,您應該能夠了解如何建立反應式資料結構,以便在狀態變更時自動追蹤依賴關係並觸發更新。這種方法將幫助您理解反應性,並為您提供自行實驗的工具,並可能將其應用到您的專案中。

讓我們開始看看我們將要使用的反應式系統的核心組件:

  • 效果:自動運行以回應反應資料變化的函數。它們是使用效果函數註冊的,該函數追蹤對任何存取訊號的依賴關係。
  • 訊號:反應性資料屬性,每當其值改變時通知依賴效應。
  • 依賴性:訊號和依賴它們的效果之間的關係。追蹤依賴關係,以便訊號的變化觸發相關效果的更新。

現在我們已經了解了響應式程式定義,讓我們也提一下我們將要使用的 Javascript API:

Proxy:Proxy 物件允許您為另一個物件建立代理,使您能夠為基本操作(如屬性存取和分配)定義自訂行為。在此程式碼中,它用於使反應式儲存(狀態物件)響應更改。

Reflect:Reflect API 提供可攔截 JavaScript 操作的方法。它用於在響應式函數中執行諸如 Reflect.get 和 Reflect.set 之類的操作,從而允許代理處理屬性存取和賦值,同時保持物件的原始行為。

Map:Map 物件是一個保存鍵值對的集合,其中鍵可以是任何資料類型。在此實作中,它用於建立 dependencyMap,該依賴關係追蹤與每個訊號關聯的依賴關係。

現在,讓我們開始定義我們的初始狀態:

// Let's define a Map object to track our dependencies
const dependencyTrackerMap = new Map();
// The activeEffect variable will hold the currently executing 
// effect function. 
// It will be set when an effect is run and will be used
// to track which effects depend on specific reactive properties. 
let activeEffect = null

// This function will make an object reactive
function reactive(target) {
    return new Proxy(target, {
        get(obj, prop) {
            trackDependency(prop); // Track dependency
            return Reflect.get(obj, prop);
        },
        set(obj, prop, value) {
            const result = Reflect.set(obj, prop, value);
            triggerDependency(prop); // Trigger reactions
            return result;
        }
    });
}

// the effect function will register reactive functions
function effect(fn) {
    activeEffect = fn;
    fn(); // Run the function once to register dependencies
    activeEffect = null;
}

// this function will track dependencies
function trackDependency(key) {
    if (activeEffect) {
        if (!dependencyTrackerMap.has(key)) {
            dependencyTrackerMap.set(key, new Set());
        }
        dependencyTrackerMap.get(key).add(activeEffect);
    }
}

// this function will trigger dependencies
function triggerDependency(key) {
    const deps = dependencyTrackerMap.get(key);
    if (deps) {
        deps.forEach(effect => effect());
    }
}

// This will create a reactive object with an initial state
// count and message here are signals
const state = reactive({ count: 0, message: "Hello" });

所以,這就是我們所做的:

  1. 我們創建了一個響應式函數,它接受一個物件並返回一個代理,該代理將追蹤將來對該物件進行的更改
  2. 我們建立了一個效果函數,它註冊依賴狀態的反應函數。定義效果後,它會立即運行以註冊任何依賴項並相應地設定 activeEffect。
  3. 我們建立了一個依賴追蹤器,它由三個部分組成:trackDependency 函數檢查當存取響應式屬性時是否有主動效果。如果是,它會將該效果新增至 dependencyTrackerMap 中對應屬性的一組相依性。反過來,triggerDependency 函數會從 dependencyTrackerMap 中擷取與屬性關聯的依賴效果集,並在屬性值變更時執行每個效果。

現在,讓我們創建一個帶有回調的效果並嘗試觸發它:

// Let's define a Map object to track our dependencies
const dependencyTrackerMap = new Map();
// The activeEffect variable will hold the currently executing 
// effect function. 
// It will be set when an effect is run and will be used
// to track which effects depend on specific reactive properties. 
let activeEffect = null

// This function will make an object reactive
function reactive(target) {
    return new Proxy(target, {
        get(obj, prop) {
            trackDependency(prop); // Track dependency
            return Reflect.get(obj, prop);
        },
        set(obj, prop, value) {
            const result = Reflect.set(obj, prop, value);
            triggerDependency(prop); // Trigger reactions
            return result;
        }
    });
}

// the effect function will register reactive functions
function effect(fn) {
    activeEffect = fn;
    fn(); // Run the function once to register dependencies
    activeEffect = null;
}

// this function will track dependencies
function trackDependency(key) {
    if (activeEffect) {
        if (!dependencyTrackerMap.has(key)) {
            dependencyTrackerMap.set(key, new Set());
        }
        dependencyTrackerMap.get(key).add(activeEffect);
    }
}

// this function will trigger dependencies
function triggerDependency(key) {
    const deps = dependencyTrackerMap.get(key);
    if (deps) {
        deps.forEach(effect => effect());
    }
}

// This will create a reactive object with an initial state
// count and message here are signals
const state = reactive({ count: 0, message: "Hello" });

當我們嘗試更新我們建立的狀態時,控制台日誌將觸發:

//We are using state from the previous snippet:
effect(() => {
    console.log(Count has changed: ${state.count});
});

effect(() => {
    console.log("Message has changed");
    console.log(The new message is: ${state.message});
});

以下是觸發依賴項時發生的情況的一些視覺化:

Build a reactive store from scratch using Javascript


在本文中,我們探討如何在 JavaScript 中建立基本的反應式系統,從而實現自動更新(或副作用)以回應資料的變化。此實現作為反應式程式設計概念的介紹,它是框架“魔法”的一部分。此外,我們還了解了 Proxy 和 Reflect API 的作用並使用了它們,以及 Map 物件。

總之,這個反應式系統管理依賴關係並在狀態變化時自動更新效果。透過註冊依賴特定反應屬性的函數,系統可以追蹤哪些函數依賴哪些屬性,並在需要時重新運行它們。這種方法允許創建響應式應用程序,其中狀態變更會自動反映在 UI 中,無需額外程式碼,從而改善開發人員體驗並使資料處理更輕鬆、更有效率。

以上是使用 Javascript 從頭開始建立反應式商店的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn