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

在納溪等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作按需搭建網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),營銷型網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站建設(shè)公司,納溪網(wǎng)站建設(shè)費(fèi)用合理。
接下來的幾篇文章里我會(huì)詳細(xì)介紹每個(gè)階段的詳細(xì)實(shí)現(xiàn)原理,希望可以給你的學(xué)習(xí)帶來幫助。
寫這篇文章的時(shí)候有很大的猶豫,擔(dān)心Solid JS受眾太小,文章的反響連”平平“都算不上,所以先寫一篇試試水,如果真的反響平平,我會(huì)暫時(shí)放棄這個(gè)寫作計(jì)劃,還請見諒!
響應(yīng)式原理
作為Solid JS響應(yīng)式的基石,我們先看看createSignal的用法和原理。接著我們手動(dòng)實(shí)現(xiàn)一個(gè)簡易版的createSignal,
萬惡之源createSignal
用法
function createSignal(
initialValue: T,
options?: { equals?: false | ((prev: T, next: T) => boolean) }
): [get: () => T, set: (v: T) => T]; Solid JS的厲害之處是,你可以定義變量是否為響應(yīng)式,甚至可以定義響應(yīng)式的時(shí)機(jī)。
- 僅提供initialValue時(shí),(默認(rèn))是響應(yīng)式的。
- 在options設(shè)置equals為false時(shí)不管何時(shí)都是響應(yīng)式。
- equals設(shè)置為函數(shù),根據(jù)新值和舊值的關(guān)系來設(shè)置何時(shí)為響應(yīng)式。
例子
下面這個(gè)例子僅僅在新的值大于舊的值(新增)時(shí),才是響應(yīng)式的。
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簡化后的邏輯如下:
實(shí)現(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];
}
// 返回當(dāng)前內(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)實(shí)現(xiàn)了createSignal基本功能了,接下來我們通過實(shí)現(xiàn)createEffect來讓它具有響應(yīng)式的能力。
createEffect
用法
createEffect接受一個(gè)副作用函數(shù),每當(dāng)它依賴的狀態(tài)發(fā)生改變時(shí),這個(gè)副作用都被執(zhí)行一次。
function createEffect(fn: (v: T) => T, value?: T): void;
例子
這是個(gè)很常見的例子。
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)知道,當(dāng)createEffect依賴項(xiàng)發(fā)生改變時(shí),副作用會(huì)也會(huì)發(fā)生改變,這是因?yàn)閏reateSignal是基于發(fā)布訂閱模式的響應(yīng)式。一個(gè)較為完整的關(guān)系如下:
實(shí)現(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];
}
// 返回當(dāng)前內(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;
}
// 每次寫入時(shí)執(zhí)行對應(yīng)的訂閱者
node.subscribers.forEach((subscriber) => subscriber());
return value;
}現(xiàn)在我們準(zhǔn)備下面的html文件
SolidJS
打開控制臺(tái)查看結(jié)果
使用window.increment模擬點(diǎn)擊事件,打印如下。
下面我們實(shí)現(xiàn)createMemo
createMemo
用法
createMemo通常用來做派生變量保存基于某個(gè)狀態(tài)中間值。完整用法如下:
function createMemo(
fn: (v: T) => T,
value?: T,
options?: { equals?: false | ((prev: T, next: T) => boolean) }
): () => T; 本篇只討論最原始的memo。
例子
一個(gè)例子如下,每當(dāng)count變化時(shí),sum自動(dòng)加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實(shí)現(xiàn)的,所以流程上來說和createEffect一樣。
真實(shí)的源碼里,是基于createComputation實(shí)現(xiàn)的,但是它的內(nèi)部是createSignal
實(shí)現(xiàn)
const createMemo = (memo) => {
const [value, setValue] = createSignal();
createEffect(() => setValue(memo()));
return value;
};接下來在測試?yán)永锾砑尤缦聝尚?/p>
const sum = createMemo(() => count() + 2)
createEffect(() => console.log('sum : ', sum()))
然后在控制臺(tái)操作
網(wǎng)頁題目:SolidJS響應(yīng)式原理和簡易實(shí)現(xiàn)
文章網(wǎng)址:http://www.5511xx.com/article/cooejeo.html


咨詢
建站咨詢
