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

基于JavaScript介紹性能爆表的SolidJS

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

前言

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

背景

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

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

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

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

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

對于我這種小項目還是比較適合的~

介紹

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

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

官方給出的理由:

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

主要優(yōu)勢

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

對比分析

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

虛擬DOM的分析

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

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

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

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

核心原理的選擇

拿我們熟悉的reactvue說明:

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

更新粒度的選擇

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

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

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

是否采用虛擬DOM

這個選擇是與上邊采用何種粒度的更新設計緊密相關的:

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

開發(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的雙胞胎兄弟...

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

調(diào)用棧分析:

簡單分析:

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

它的響應式實現(xiàn)確實是與vue一樣,都是基于發(fā)布訂閱的依賴收集去做的,但它沒有采用vue虛擬Dom的運行時diff,而是充分在編譯階段做文章,將狀態(tài)更新編譯為獨立的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 操作,自然可以省去大量的運行時代碼。而是使用了solid-js/web庫提供的insert等DOM函數(shù)操作。

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

項目實戰(zhàn)

直接按照官方文檔示例,創(chuàng)建一個支持TypeScript的基礎項目,模板默認使用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è)務代碼了,就是這么簡單~

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

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

總結(jié)

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

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

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

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

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

相關文章

  • JavaScript中Promise處理異步的并行與串行

    JavaScript中Promise處理異步的并行與串行

    js中的promise是一個異步編程的解決方案,語法層面上他是一個構(gòu)造函數(shù),名字為Promise(),下面這篇文章主要給大家介紹了關于JavaScript中Promise處理異步的并行與串行的相關資料,需要的朋友可以參考下
    2022-12-12
  • js簡單正則驗證漢字英文及下劃線的方法

    js簡單正則驗證漢字英文及下劃線的方法

    這篇文章主要介紹了js簡單正則驗證漢字英文及下劃線的方法,結(jié)合完整實例形式分析了javascript針對中英文字母與下劃線的正則驗證方法,需要的朋友可以參考下
    2016-11-11
  • 鼠標移動到圖片名上,顯示圖片的簡單實例

    鼠標移動到圖片名上,顯示圖片的簡單實例

    鼠標移動到名(wait.gif)上,顯示圖片,鼠標移開則不顯示圖片
    2013-07-07
  • JavaScript閉包_動力節(jié)點Java學院整理

    JavaScript閉包_動力節(jié)點Java學院整理

    這篇文章主要介紹了JavaScript閉包,閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高級應用都要依靠閉包實現(xiàn)
    2017-06-06
  • ES6箭頭函數(shù)和擴展實例分析

    ES6箭頭函數(shù)和擴展實例分析

    這篇文章主要介紹了ES6箭頭函數(shù)和擴展,結(jié)合實例形式分析了ES6箭頭函數(shù)和擴展基本功能、用法及操作注意事項,需要的朋友可以參考下
    2020-05-05
  • javascript去掉前后空格的實例

    javascript去掉前后空格的實例

    在js中去除空格并不是可以直接使用trim來刪除,它在js中并不像我們想的那么好用,特別像我要刪除前后空格這個trim函數(shù)更不可靠了
    2013-11-11
  • 手寫Spirit防抖函數(shù)underscore和節(jié)流函數(shù)lodash

    手寫Spirit防抖函數(shù)underscore和節(jié)流函數(shù)lodash

    這篇文章主要介紹了手寫Spirit防抖函數(shù)underscore和節(jié)流函數(shù)lodash,接下來將會帶你們了解下這兩者的區(qū)別,以及我們該如何手寫實現(xiàn)這兩個函數(shù)
    2022-03-03
  • layui動態(tài)加載多表頭的實例

    layui動態(tài)加載多表頭的實例

    今天小編就為大家分享一篇layui動態(tài)加載多表頭的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • 跟我學習javascript的執(zhí)行上下文

    跟我學習javascript的執(zhí)行上下文

    跟我學習javascript的執(zhí)行上下文,讀完本文后,你應該清楚了解釋器做了什么,為什么函數(shù)和變量能在聲明前使用以及它們的值是如何決定的,需要了解這些內(nèi)容的朋友可以參考下
    2015-11-11
  • JS Select下拉框(支持輸入模糊查詢)

    JS Select下拉框(支持輸入模糊查詢)

    這篇文章主要為大家詳細介紹了JS Select下拉框的相關資料,支持輸入模糊查詢,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評論