成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SolidJS響應式原理和簡易實現

開發 前端
作為Solid JS響應式的基石,我們先看看createSignal的用法和原理。接著我們手動實現一個簡易版的createSignal。

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

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

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

響應式原理

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

?? 萬惡之源createSignal

?? 用法

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

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

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

?? 例子

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

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 (
    <>
      <button type="button" onClick={increment}>
        +
      </button>
      <button type="button">{count()}</button>
      <button type="button" onClick={reduce}>
        -
      </button>
    </>
  );
}

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

?? 原理

createSignal簡化后的邏輯如下:

圖片

?? 實現

const signalOptions = {
  equals: false
};

function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 創建內部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];
}
// 返回當前內部signal的value
function readSignal() {
  return this.value;
}
// 更新內部的value,然后返回value
function writeSignal(node, value) {
  if (!node.comparator) {
    node.value = value;
  }
  return value;
}

現在我們已經實現了createSignal基本功能了,接下來我們通過實現createEffect來讓它具有響應式的能力。

??createEffect

?? 用法

createEffect接受一個副作用函數,每當它依賴的狀態發生改變時,這個副作用都被執行一次。

function createEffect<T>(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 (
    <button type="button" onClick={increment}>
      {count()}
    </button>
  );
}

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

?? 原理

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

圖片

?? 實現

const signalOptions = {
  equals: false
};

const observers = []

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

function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 創建內部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];
}

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

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

現在我們準備下面的html文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SolidJS</title>
</head>
<body>
  <h1>打開控制臺查看結果</h1>
  <script src="./solid.js"></script>
  <script>
    const [count, setCount] = createSignal(1);
    const increment = () => setCount(count() + 1);
    createEffect(() => console.log('count : ', count()))
    window.increment = increment
  </script>
</body>
</html>

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

圖片

下面我們實現createMemo

?? createMemo

?? 用法

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

function createMemo<T>(
    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 (
    <button type="button" onClick={increment}>
      {count()}
    </button>
  );
}

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

?? 原理

它的內部是使用createSignal實現的,所以流程上來說和createEffect一樣。

真實的源碼里,是基于createComputation實現的,但是它的內部是createSignal

圖片

?? 實現

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

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

  return value;
};

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

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

然后在控制臺操作

圖片

責任編輯:武曉燕 來源: 萌萌噠草頭將軍
相關推薦

2020-06-09 11:35:30

Vue 3響應式前端

2016-12-21 14:35:46

響應式網頁布局實現方法原理

2021-06-10 08:29:15

Rollup工具前端

2019-07-01 13:34:22

vue系統數據

2021-01-22 11:47:27

Vue.js響應式代碼

2017-08-30 17:10:43

前端JavascriptVue.js

2023-06-01 19:19:41

2012-05-27 18:28:46

jQuery Mobi

2022-09-02 10:34:23

數據Vue

2021-08-31 07:02:34

數據響應Vue偵測數據變化

2022-03-09 23:02:30

Java編程處理模型

2021-09-27 06:29:47

Vue3 響應式原理Vue應用

2023-10-12 22:44:16

iOS事件響應鏈

2012-02-21 16:39:29

響應式Web設計

2022-06-26 00:00:02

Vue3響應式系統

2023-06-02 16:28:01

2021-01-25 05:38:04

設計原理VueSubject

2013-02-21 09:54:12

響應式重構Web

2023-06-06 15:38:28

HTMLCSS開發

2024-01-09 09:40:23

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 嫩草黄色影院 | 综合激情av | 日韩欧美在线视频 | 亚洲国产网站 | 日本福利视频 | 国外成人免费视频 | 亚洲午夜精品一区二区三区他趣 | 久久国产精品网站 | 精品一区二区三区免费视频 | 亚州综合在线 | 国产精品久久久久久一区二区三区 | 黄色片视频 | 91精品国产乱码久久蜜臀 | 国产精品夜色一区二区三区 | 亚洲精品久久久一区二区三区 | 女女爱爱视频 | 精品香蕉一区二区三区 | 国产精品国色综合久久 | 99视频在线 | 日韩欧美中文在线 | 狠狠av| 亚洲精品一 | 精品亚洲永久免费精品 | 国产男女猛烈无遮掩视频免费网站 | 中文字幕免费视频 | 在线亚洲电影 | 免费福利视频一区二区三区 | 一区二区三区国产精品 | 欧美一区二区 | 亚洲人在线观看视频 | 午夜视频网站 | 国产精品99免费视频 | 国产99小视频 | 免费观看一区二区三区毛片 | 精品一二区 | 欧美一级在线观看 | 欧美一级欧美一级在线播放 | 在线国产视频 | 久久另类视频 | 国产精品乱码一区二三区小蝌蚪 | 伊人国产精品 |