欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于JavaScript介紹性能爆表的SolidJS

 更新時間:2022年09月08日 09:14:01   作者:小帥不太帥???????  
這篇文章主要介紹了基于JavaScript介紹性能爆表的SolidJS,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

前言

使用預(yù)編譯、無虛擬DOM、究極融合怪、性能爆表、React的異父異母親兄弟——SolidJs

背景

前段時間,產(chǎn)品提了個臨時需求,讓我給開發(fā)一個獨(dú)立部署的首頁可視化頁面,因?yàn)槟壳拔覀兿到y(tǒng)提供以iframe的方式實(shí)現(xiàn)用戶自己選擇URL配置一個頁面,作為應(yīng)用的其中一個路由頁面使用~

想著就單獨(dú)部署一個頁面,也沒必要使用React或者Vue了,簡單畫個頁面完事,jq我是用不動了

想著最近出社區(qū)也涌現(xiàn)了不少有趣的框架,之前看svelte,就覺得挺有意思的,感覺也比較符合我的使用場景,正準(zhǔn)備用這個上手搞一波呢

然后,在GitHub發(fā)現(xiàn)了solidjs這個項(xiàng)目,大致看了下,好家伙,這簡直比reactreact??~

看了下文檔,寫了demo試了下,很容易上手,又看了一些對比測試和博客介紹,感覺性能很強(qiáng)啊,和svelte一樣都是預(yù)編譯,沒有運(yùn)行時,構(gòu)建產(chǎn)物十幾kb,與原生js相差無幾,令人驚嘆~

對于我這種小項(xiàng)目還是比較適合的~

介紹

官方介紹:用于構(gòu)建用戶界面的聲明式、高效且靈活的 JavaScript

Solid 使用了類似 Svelte 的預(yù)編譯,語法使用上類似于 React,使用 JSX 語法和非常相像的API,但不同于 React,組件只會初始化一次,并不是 state 改變就重新運(yùn)行渲染整個組件,這類似于 Vue3 的 setup和響應(yīng)式更新(更新顆粒度為節(jié)點(diǎn)級)

官方給出的理由:

  • 高性能 - 始終在公認(rèn)的 UI 速度和內(nèi)存利用率基準(zhǔn)測試中名列前茅
  • 強(qiáng)大 - 可組合的反應(yīng)式原語與 JSX 的靈活性相結(jié)合
  • 務(wù)實(shí) - 合理且量身定制的 API 使開發(fā)變得有趣而簡單
  • 生產(chǎn)力 - 人體工程學(xué)和熟悉程度使構(gòu)建簡單或復(fù)雜的東西變得輕而易舉

主要優(yōu)勢

  • 高性能 - 接近原生的性能,在 js-framework-benchmark 排名中名列前茅
  • 極小的打包體積 - 編譯為直接的DOM操作,無虛擬DOM,極小的運(yùn)行時(類似于 Svelte),適合打?yàn)楠?dú)立的 webComponent 在其它應(yīng)用中嵌入
  • 易于使用 - 近似 React 的使用體驗(yàn),便于快速上手

對比分析

我們把關(guān)注點(diǎn)聚焦于是否使用虛擬DOM,以及數(shù)據(jù)的響應(yīng)處理。

虛擬DOM的分析

首先,虛擬DOM并不是一定比原生性能好,或者說是更快,拋開真實(shí)場景不談都是瞎扯淡,框架的設(shè)計(jì)和應(yīng)用場景是有它自身考量的。

在狀態(tài)與Dom操作之間抽象出一層虛擬Dom,需要犧牲一定的運(yùn)行時性能,并不一定比直接操作原生Dom快,要看情況,畢竟diff并不是免費(fèi)的。

  • 不管你的數(shù)據(jù)變化多少,每次重繪的性能都是可以接受(提供過的去的性能)。
  • 你依然可以用類似 innerHTML 的思路去寫你的應(yīng)用。
  • 最最重要的一點(diǎn),實(shí)現(xiàn)了跨平臺。

react,對于web端的渲染可以使用react-dom,對于native的渲染可以使用react-native、以及服務(wù)端渲染等,他們的開發(fā)模式非常類似,按照react的語法規(guī)則進(jìn)行即可,但是在render層,只要符合react api規(guī)范,你可以提供各種不同的render渲染函數(shù),進(jìn)行跨平臺的渲染實(shí)現(xiàn)。

核心原理的選擇

拿我們熟悉的reactvue說明:

  • React對數(shù)據(jù)的處理是不可變(immutable):具體表現(xiàn)是整樹更新,更新時,不關(guān)注是具體哪個狀態(tài)變化了,只要有狀態(tài)改變,直接整樹diff找出差異進(jìn)行對應(yīng)更新。
  • Vue對數(shù)據(jù)的處理是響應(yīng)式、可變的(mutable):更新時,能夠精確知道是哪些狀態(tài)發(fā)生了改變,能夠?qū)崿F(xiàn)精確到節(jié)點(diǎn)級別的更新(類似的框架還有Svelte、SolidJS)。

更新粒度的選擇

  • 應(yīng)用級:有狀態(tài)改變,就更新整個應(yīng)用,生成新的虛擬Dom樹,與舊樹進(jìn)行Diff(代表作:React,當(dāng)然了,現(xiàn)在它的虛擬Dom已升級為了Fiber)。
  • 組件級:與上方類似,只不過粒度小了一個等級(代表作:vuev2及之后的版本)。
  • 節(jié)點(diǎn)級:狀態(tài)更新直接與具體的更新節(jié)點(diǎn)的操作綁定(代表作vue1.x、SvelteSolidJS)。

vue1.x時代,對于數(shù)據(jù)是每個生成一個對應(yīng)的Wather,更新顆粒度為節(jié)點(diǎn)級別,但這樣創(chuàng)建大量的Wather會造成極大的性能開銷,因此在vue2.x時代,通過引入虛擬DOM優(yōu)化響應(yīng),做到了組件級顆粒度的更新。

而對于react來說,虛擬DOM就是至關(guān)重要的部分,甚至是核心,我們已經(jīng)了解react是屬于應(yīng)用級別的更新,因此整個DOM樹的更新開銷是極大的,所以這里對于虛擬DOM+diff算法的使用就是極其必要的。包括現(xiàn)在的fiber架構(gòu)與可中斷更新,也算是對虛擬DOM的極致壓榨。

是否采用虛擬DOM

這個選擇是與上邊采用何種粒度的更新設(shè)計(jì)緊密相關(guān)的:

  • :對應(yīng)用級的這種更新粒度,虛擬Dom簡直是必需品,因?yàn)樵?code>diff前它并不能得到此次更新的具體節(jié)點(diǎn)信息,必須要通過隨后的虛擬Dom+Diff算法篩選出最小差異,不然整樹append對性能是災(zāi)難(代表框架:React、vue)。
    • 但這里值得注意的事是:本質(zhì)上vue并不需要虛擬DOM,因?yàn)樗@種基于依賴收集的響應(yīng)式機(jī)制可以直接進(jìn)行節(jié)點(diǎn)級更新,但vue借助虛擬DOM的抽象能力,可以做到更新粒度的隨意調(diào)整(目前是組件級),給vue的發(fā)展提供更多可能性, 尤其在跨平臺渲染方面,這點(diǎn)十分關(guān)鍵。
  • :對節(jié)點(diǎn)級更新粒度的框架來說,一般沒有必要采用虛擬dom(代表作:vue1.x、SvelteSolidJS)。

開發(fā)語法DSL選擇

  • JSXReact、SolidJS
  • 模版+編譯指令vue(JSX可選)、Svelte

正文

基本使用

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

const CountingComponent = () => {
  const [count, setCount] = createSignal(0);

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

  const handleAdd = () => {
    setCount((prev) => prev + 1);
  };

  return <div onClick={handleAdd}>Count value is {count()}</div>;
};
render(() => <CountingComponent />, document.getElementById('app'));

這簡直是React hooks的雙胞胎兄弟...

而且因?yàn)?strong>SolidJS這種后發(fā)優(yōu)勢,沒有React沉重的歷史包袱,比如不需要處理類組件的兼容(SolidJS只支持函數(shù)式)這讓它在實(shí)現(xiàn)了大部分React功能特性的前提下,源碼體積要比React小很多,這讓它在首屏加載方面就首先占據(jù)上風(fēng)。直接調(diào)用編譯好的DOM操作方法,省去了虛擬DOM比較這一步所消耗的時間,整個更新鏈路相比React變得簡潔許多。

調(diào)用棧分析:

簡單分析:

  • 組件函數(shù)只會在整個應(yīng)用生命周期里調(diào)用一次。
  • 心智模型與react完全不一樣,反而與vue3保持了一致,可以說兼具了React hooks + vue3的優(yōu)點(diǎn)
  • createEffect自動追蹤依賴,不需要像react那樣維護(hù)一個dep數(shù)組
  • hook調(diào)用順序沒要求,以函數(shù)調(diào)用的方式解決Proxy目標(biāo)必須是對象的問題

它的響應(yīng)式實(shí)現(xiàn)確實(shí)是與vue一樣,都是基于發(fā)布訂閱的依賴收集去做的,但它沒有采用vue虛擬Dom的運(yùn)行時diff,而是充分在編譯階段做文章,將狀態(tài)更新編譯為獨(dú)立的DOM操作方法。

編譯內(nèi)容分析

import { render, createComponent, delegateEvents, insert, template } from 'solid-js/web';
import { createSignal, createEffect } from 'solid-js';

const _tmpl$ = /*#__PURE__*/template(`<div>Count value is </div>`, 2);

const CountingComponent = () => {
  const [count, setCount] = createSignal(0);
  createEffect(() => console.log('count', count()));

  const handleAdd = () => {
    setCount(prev => prev + 1);
  };

  return (() => {
    const _el$ = _tmpl$.cloneNode(true);
          _el$.firstChild;

    _el$.$$click = handleAdd;

    insert(_el$, count, null);

    return _el$;
  })();
};
render(() => createComponent(CountingComponent, {}), document.getElementById('app'));
delegateEvents(["click"]);

可以看到,跟基于 Virtual DOM 的框架相比,這樣的輸出不需要 Virtual DOM 的 diff/patch 操作,自然可以省去大量的運(yùn)行時代碼。而是使用了solid-js/web庫提供的insert等DOM函數(shù)操作。

再結(jié)合以后的webcomponent考慮下,真是大有可為,發(fā)展空間很大,未來可期~

項(xiàng)目實(shí)戰(zhàn)

直接按照官方文檔示例,創(chuàng)建一個支持TypeScript的基礎(chǔ)項(xiàng)目,模板默認(rèn)使用vite構(gòu)建(solidjs-templates

# Typescript template
$ npx degit solidjs/templates/ts my-solid-project
$ cd my-solid-project
$ npm install # or pnpm install or yarn install

在vite中引入插件

import solidPlugin from "vite-plugin-solid"

export default defineConfig({
  plugins: [solidPlugin()],
})

入口文件配置如下:

import { render } from "solid-js/web"
import App from "./App"

render(() => <App />, document.getElementById("root"))

接下來就可以開始寫業(yè)務(wù)代碼了,就是這么簡單~

import { Title, List, Chart } from "./components"
import { onMount, onCleanup, createSignal } from "solid-js"
import request from "./utils/request"
import type { Component } from "solid-js"
import type { DataProps, ValueType } from "./typings"
import cls from "./index.module.less"

const URL = "/statistic/hrm"

const App: Component = () => {
  const [getValue, setValue] = createSignal<ValueType>(null)

  // mount
  onMount(() => {
    request<DataProps>({ method: "GET", url: URL }).then((res) => {
      if (res) {
        console.log("res", res)
        setValue(res)
      }
    })
  })

  // unmount
  onCleanup(() => {
    // ...
  })
  return (
    <div class={cls.App}>
      <Title />
      <List list={getValue()?.list} />
      {getValue()?.pieData && <Chart data={getValue()?.pieData} />}
    </div>
  )
}
export default App

List組件

import type { Component } from "solid-js"
import { ListProps } from "../typings"

import cls from "../index.module.less"

// List
const List: Component<{ list: ListProps[] }> = (props) => {
  return (
    <ul class={cls.list}>
      {props.list?.map(({ label, value }) => (
        <li>
          <div class={cls.label}>{label}</div>
          <div class={cls.value}>{value}</div>
        </li>
      ))}
    </ul>
  )
}
export default List

Echart可視化組件

import { onMount, onCleanup } from "solid-js"
import type { Component } from "solid-js"
import echarts, { ECOptionPie } from "../../utils/echart"
import { OptionProps } from "../../typings"

// Chart
const Chart: Component<{ data: OptionProps[] }> = (props) => {
  let container: null | HTMLDivElement = null
  let instance

  // 性別分布
  const Option: ECOptionPie = {
    // data: props.data || [],
    // ...
  }
  onMount(() => {
    instance = echarts.init(container)
    instance.setOption(Option)
    window.addEventListener("resize", () => instance?.resize())
  })
  onCleanup(() => {
    window.removeEventListener("resize", () => instance?.resize())
  })
  return <div ref={container}></div>
}
export default Chart

以上是我基于項(xiàng)目簡化的demo,怎么樣,看起來是不是和react特別像??,使用起來也是相當(dāng)簡單了~

總結(jié)

自react和虛擬DOM誕生以來,整個前端的開發(fā)范式都發(fā)生了翻天覆地的變化,各種類似框架也是層出不窮,他們各有各的優(yōu)勢。

對我們開發(fā)者來說,對于同一類型框架熟練掌握一種足矣,大可不必每種框架都學(xué)習(xí)一遍,我們需要做到對其內(nèi)部實(shí)現(xiàn)原理的知悉,做到知其然也知其所以然,正所謂一法通萬法皆通,當(dāng)我們打牢基礎(chǔ)之后再去使用和學(xué)習(xí)其他框架便輕而易舉了,并在實(shí)踐中拓展知識廣度和深度。

對于不同類型框架,了解其優(yōu)勢以及一些獨(dú)有的特殊思路和實(shí)現(xiàn),做到心中有數(shù),也有益于我們的技術(shù)成長。

這樣我們在之后的實(shí)際開發(fā)過程中便可結(jié)合具體場景做到更合適的技術(shù)選型~

到此這篇關(guān)于基于JavaScript介紹性能爆表的SolidJS的文章就介紹到這了,更多相關(guān)JS SolidJS內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論