日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
SolidJS響應式原理和簡易實現(xiàn)

上篇文章中主要介紹了Solid JS的基本語法,分階段粗略地介紹了一些原理(響應式原理、編譯原理和運行時原理)。

在納溪等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供網(wǎng)站設計、做網(wǎng)站 網(wǎng)站設計制作按需搭建網(wǎng)站,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,高端網(wǎng)站設計,營銷型網(wǎng)站建設,成都外貿(mào)網(wǎng)站建設公司,納溪網(wǎng)站建設費用合理。

接下來的幾篇文章里我會詳細介紹每個階段的詳細實現(xiàn)原理,希望可以給你的學習帶來幫助。

寫這篇文章的時候有很大的猶豫,擔心Solid JS受眾太小,文章的反響連”平平“都算不上,所以先寫一篇試試水,如果真的反響平平,我會暫時放棄這個寫作計劃,還請見諒!

響應式原理

作為Solid JS響應式的基石,我們先看看createSignal的用法和原理。接著我們手動實現(xiàn)一個簡易版的createSignal,

萬惡之源createSignal

用法

function createSignal(
    initialValue: T,
    options?: { equals?: false | ((prev: T, next: T) => boolean) }
): [get: () => T, set: (v: T) => T];

Solid JS的厲害之處是,你可以定義變量是否為響應式,甚至可以定義響應式的時機。

  • 僅提供initialValue時,(默認)是響應式的。
  • 在options設置equals為false時不管何時都是響應式。
  •  equals設置為函數(shù),根據(jù)新值和舊值的關系來設置何時為響應式。

例子

下面這個例子僅僅在新的值大于舊的值(新增)時,才是響應式的。

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(1, { equals: (n, o) => n > o });
  const increment = () => setCount(count() + 1);
  const reduce = () => setCount(count() - 1);

  return (
    <>
      
      
      
    
  );
}

render(() => , document.getElementById("app")!);

原理

createSignal簡化后的邏輯如下:

實現(xiàn)

const signalOptions = {
  equals: false
};

function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 創(chuàng)建內(nèi)部signal
  const s = {
    value,
    comparator: options.equals || undefined
  };
 
  // 定義setter
  const setter = value => {
    if (typeof value === "function") {
      value = value(s.value);
    }
    return writeSignal(s, value);
  };
  // 返回[getter, setter]
  return [readSignal.bind(s), setter];
}
// 返回當前內(nèi)部signal的value
function readSignal() {
  return this.value;
}
// 更新內(nèi)部的value,然后返回value
function writeSignal(node, value) {
  if (!node.comparator) {
    node.value = value;
  }
  return value;
}

現(xiàn)在我們已經(jīng)實現(xiàn)了createSignal基本功能了,接下來我們通過實現(xiàn)createEffect來讓它具有響應式的能力。

createEffect

用法

createEffect接受一個副作用函數(shù),每當它依賴的狀態(tài)發(fā)生改變時,這個副作用都被執(zhí)行一次。

function createEffect(fn: (v: T) => T, value?: T): void;

例子

這是個很常見的例子。

import { render } from "solid-js/web";
import { createSignal, createEffect } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);

  createEffect(() => console.log('count : ', count()))
  return (
    
  );
}

render(() => , document.getElementById("app")!);

原理

我們已經(jīng)知道,當createEffect依賴項發(fā)生改變時,副作用會也會發(fā)生改變,這是因為createSignal是基于發(fā)布訂閱模式的響應式。一個較為完整的關系如下:

實現(xiàn)

const signalOptions = {
  equals: false
};

const observers = []

function createEffect (effect) {
  const execute = () => {
    // 保存在observers中
    observers.push(execute);
    try {
      effect();
    } finally {
      // 釋放
      observers.pop();
    }
  };
  // 副作用函數(shù)立即執(zhí)行
  execute();
};

function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 創(chuàng)建內(nèi)部signal
  const s = {
    value,
    // 保存訂閱者
    subscribers: new Set(),
    comparator: options.equals || undefined
  };
 
  // 定義setter
  const setter = value => {
    if (typeof value === "function") {
      value = value(s.value);
    }
    return writeSignal(s, value);
  };
  // 返回[getter, setter]
  return [readSignal.bind(s), setter];
}

// 返回當前內(nèi)部signal的value
function readSignal() {
  const curr = observers[observers.length - 1]
  curr && this.subscribers.add(curr)
  return this.value;
}

// 更新內(nèi)部的value,然后返回value
function writeSignal(node, value) {
  if (!node.comparator) {
    node.value = value;
  }
  // 每次寫入時執(zhí)行對應的訂閱者
  node.subscribers.forEach((subscriber) => subscriber());
  return value;
}

現(xiàn)在我們準備下面的html文件




  
  
  
  SolidJS


  

打開控制臺查看結(jié)果

使用window.increment模擬點擊事件,打印如下。

下面我們實現(xiàn)createMemo

 createMemo

用法

createMemo通常用來做派生變量保存基于某個狀態(tài)中間值。完整用法如下:

function createMemo(
    fn: (v: T) => T,
    value?: T,
    options?: { equals?: false | ((prev: T, next: T) => boolean) }
): () => T;

本篇只討論最原始的memo。

例子

一個例子如下,每當count變化時,sum自動加2

import { render } from "solid-js/web";
import { createSignal, createEffect, createMemo } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);

  const sum = createMemo(() => count() + 2)
  
  createEffect(() => console.log('sum : ', sum()))
  
  createEffect(() => console.log('count : ', count()))
  
  return (
    
  );
}

render(() => , document.getElementById("app")!);

原理

它的內(nèi)部是使用createSignal實現(xiàn)的,所以流程上來說和createEffect一樣。

真實的源碼里,是基于createComputation實現(xiàn)的,但是它的內(nèi)部是createSignal

實現(xiàn)

const createMemo = (memo) => {
  const [value, setValue] = createSignal();

  createEffect(() => setValue(memo()));

  return value;
};

接下來在測試例子里添加如下兩行

const sum = createMemo(() => count() + 2)
createEffect(() => console.log('sum : ', sum()))

然后在控制臺操作


網(wǎng)頁標題:SolidJS響應式原理和簡易實現(xiàn)
網(wǎng)頁路徑:http://www.dlmjj.cn/article/cooejeo.html