React 開發者們的 Solid-js 快速入門教程

作者 | Travis Waith-Mair

譯者 | 馬可薇

策劃 | 鄧豔琴

關於 Solid.js 與 React 之間的相似、不同以及你需要留意的陷阱。

在 2021 年的 JavaScript 調查問卷中,黑馬 Solid.js 一騎當先登上榜首,在用戶滿意度的評分上連超兩大競爭對手,React 和 Svelte。雖然 React 仍有着不錯的市場佔有率,但要小瞧了 Solid.js 那可是犯了個大錯誤。

React 開發者們會發現 Solid 非常眼熟

先看一眼下面這段用 Solid.js 寫的簡單計數程序:

function Counter() {
  const [count, setCount] = createSignal(0);
  return (
    <div>
      <p>The current count is: {count()}</p>
      <button onClick={() => setCount((x) => x + 1)}>Plus</button>
    </div>
  );
}

我敢打包票,即使從來沒接觸過 Solid.js,React 的開發者們讀這段代碼也是完全不費力。這是因爲 Solid.js 在 API 上和 React 有着異曲同工之妙。其中一個原因是 Solid.js 也使用了 JSX,意味着 React 開發者們刻在 DNA 裏關於元素和組件的應用方式也會在 Solid.js 裏體現。比如說下面這個 “歡迎” 組件,我們完全可以以和 React 應用類型的方式來實現:

function Welcome(props) {
  return <p>Welcome, {props.name}</p>;
}

這二者之間的相似之處不僅限於此,Solid.js 在圖元的使用上也和 React 的 hook 類似,大部分 Solid 響應式圖元的 API 你都可以在 React 的 hook 找到對應的存在。

但請注意,Solid.js 可不是 React API 的複製品,React 應用直接放到 Solid.js 中運行是肯定行不通的。但不得不說,有這麼個和 React 如此相似的 API 對大部分開發者來說都是件好事,至少學習曲線不會太過陡峭。

一切都是爲了圖元

儘管這二者在表面上有如此多的相似點,但他們之間的不同之處纔是讓 Solid.js 得以在衆多競爭者中脫穎而出,比如說,Solid.js 的應用並不是圍着組件轉的。Solid 曾驕傲地稱他們的組件爲 “消失的組件”。在組織代碼階段,Solid 的組件很有幫助,但等到了初始的渲染階段,你就再也見不到它們了。

與 React 不同,Solid.js 的宇宙中心其實是圖元。Solid 有着一套 “完善的響應式圖元”。這些圖元功能類似 React 的 hook,但又有着些許不同。對 React 來說,hook 是獨立於 React 的組件生命週期的,需要使用者對虛擬 DOM 和 React 的渲染生命週期有一定的瞭解。而它的這種獨立性也就意味着開發者們需要下很深的工夫才能玩轉 hook。首先讓我們以 React 的組件爲例:

function Counter() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `The current count is: ${count}`;
  }, [count]);
  return (
    <div>
      <p>The current count is: {count}</p>
      <button onClick={() => setCount((x) => x + 1)}>Plus</button>
    </div>
  );
}

雖然這個例子並不難,但其中也涉及了幾條必不可少的規則,忽略這些規則將帶來一些不必要的麻煩。但 Solid 的響應式圖元就不同了,它們可以讓你用起來沒有後顧之憂。你可以選擇性地調用這些圖元,就連組件裏你都可以選擇不調用。用 Solid 來重寫上面的例子,就像這樣:

const [count, setCount] = createSignal(0);
createEffect(() => {
  document.title = `The current count is: ${count()}`;
});
function Counter() {
  return (
    <div>
      <p>The current count is: {count()}</p>
      <button onClick={() => setCount((x) => x + 1)}>Plus</button>
    </div>
  );
}

把所有的響應式圖元全部挪到了組件之外、方法之前。我們能這麼做的原因完全是因爲 Solid 是以響應式圖元本身爲基礎搭建的,而不是完全依賴組件。

響應式還是虛擬 DOM

就像是其他大衆框架,“虛擬 DOM” 這個概念是 React 框架的核心。虛擬 DOM 是指在內存中用於描述真實 DOM 的 JS 對象。因爲創建虛擬 DOM 的成本要遠小於創建一個真實的 DOM,所以多次運行組件或者對虛擬 DOM 進行更新時的消耗也會更小。除非是對真實的 DOM 進行修改,React 纔會對虛擬 DOM 進行更新,使其與真實的 DOM 相符。想在 React 中熟練調用 hook,就意味着開發者們要對虛擬 DOM 的生命週期有一定的瞭解。

而另一方面,Solid.js 更依靠一套 “完善的” 響應式。舉例來說,Solid 程序中的 JSX 語句依賴於一個響應式信號,也就是說,只有依賴於這個信號數值的 JSX 纔會隨着信號的變更在方法中被重新調用。同理,所有在 creatEffect 圖元中運行的效果也是一樣,如果這個效果依賴於一個或多個響應式數值,那麼只有在這些數值變更時纔會重新渲染。這樣一來,依賴數組也不需要了,因爲 Solid 已經提前知道那些數值可以變更,以及受這些響應式數值影響需要重新渲染的效果都有那些。

這也就是爲什麼前文會說 Solid 中組件 “消失不見”,以及是如何在組件之外調用響應式圖元的了。在初始的渲染之後,只有應用中“完善” 的部分會繼續存在。

來自 React 的 “小玩笑”

搞清楚這兩個框架的底層工作原理大概會讓不少 React 開發者們在初次嘗試 Solid 時手忙腳亂。首先你重新學習的就是,組件並不會重新運行。也就是說,我們在 React 中學到的大部分規矩都不再適用於 Solid.js。我們不需要用 useCallback 或者 useRef 來調用 hook,因爲組件都是一次性的。而如果我們想要在 JavaScript 裏賦值給變量,只需要這麼做:

function MyForm() {
  const handleSubmit = (e) => {
    /* handl submit */
  };
  let myInput;
  // use onMount or createEffect to read after connected to DOM
  onMount(() => myInput.focus());
  return (
    <form onSubmit={handleSubmit}>
      <input ref={myInput} />
    </form>
  );
}

第二點要重新熟悉的是,在銷燬 prop 函數的時候,Solid.js 的那些細粒度的響應式也會被銷燬,雖然你可能並沒有在 prop 對象中存儲任何響應式數值,但要記住,這些對象一旦被銷燬,這些響應式也就全沒了。這也就是並不推薦下面這種代碼的原因:

function Greeting(props) {
  const { greeting, name } = props;
  return (
    <h3>
      {greeting} {name}
    </h3>
  );
}

但如果你寫成這個樣子,那麼效果會好很多:

function Greeting(props) {
  return (
    <h3>
      {props.greeting} {props.name}
    </h3>
  );
}

或者可以直接利用 Solid 的 mergeProps 或者 splitProps 函數,在不影響響應式的情況下對帶有響應式數值的對象進行合併或拆散。

在 React 面世的時候,它挑戰了當時最優秀的架構,並影響着我們現今編寫網頁應用的方式。而現在 Solid 要做的,就是再次重現當年 React 的影響。

原文鏈接:

https://non-traditional.dev/an-intro-to-solidjs-for-react-developers

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/59iyt1swB4fmXJb5_7vwNw