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

雙向綁定與單向數(shù)據(jù)流之爭(zhēng),Solid會(huì)取代React嗎

開(kāi)發(fā) 前端
雙向綁定是一種傳統(tǒng)的解決方案,與之相對(duì)比,在前端領(lǐng)域 React 的解決方案是一個(gè)巨大的創(chuàng)新。單向數(shù)據(jù)流,Diff算法,雙緩存策略,優(yōu)先級(jí)隊(duì)列,任務(wù)中斷,瀏覽器空閑時(shí)間,并發(fā),函數(shù)式編程,自定義Hook... 等等許多概念都極大的擴(kuò)展了前端開(kāi)發(fā)的技術(shù)視野。

現(xiàn)在有一種觀點(diǎn)聲音逐漸大了起來(lái),認(rèn)為市面上出現(xiàn)了許多比 React 性能更好的框架,是不是意味著,React 將要被淘汰了?

所以有人就在群里問(wèn)我,他覺(jué)得 Solid.js 性能比 React 更好,以后會(huì)不會(huì)取代 React?

談?wù)勎业目捶ǎ瑏?lái)做一個(gè)深入一點(diǎn)的分析。

先說(shuō)結(jié)論:Solid.js 要取代 React 很難。

雙向綁定

雙向綁定的概念并非一個(gè)新的詞,因此對(duì)應(yīng)的解決方案 Signal ,也并非一個(gè)新的技術(shù)方案,他比 react 的存在要早得多。

Signal 是一個(gè)傳統(tǒng)技術(shù)方案。

恰恰相反,單向數(shù)據(jù)流反而是一種技術(shù)創(chuàng)新。

在雙向綁定的建立過(guò)程中,有一個(gè)理想的結(jié)果:我們可以輕易的知道數(shù)據(jù)與 DOM 節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系。如果這個(gè)理想的結(jié)果能夠輕松達(dá)成,那么通過(guò)數(shù)據(jù)驅(qū)動(dòng) UI 的形式來(lái)開(kāi)發(fā)代碼將會(huì)變得非常容易。

但是真實(shí)情況是,數(shù)據(jù)與 UI 的對(duì)應(yīng)關(guān)系很難建立。

雙向綁定采取的措施是遞歸遍歷監(jiān)聽(tīng)所有數(shù)據(jù),依次建立與對(duì)應(yīng) UI 的綁定關(guān)系。這種解決方案所花費(fèi)的成本主要體現(xiàn)在對(duì)數(shù)據(jù)的處理上。

他面臨兩個(gè)問(wèn)題。

一是數(shù)據(jù)的變化需要監(jiān)聽(tīng),但是某些數(shù)據(jù)類型的監(jiān)聽(tīng)在實(shí)現(xiàn)上有難度。

以數(shù)組為例,在以前的 vue 版本中,Object.defineProperty() 因?yàn)闊o(wú)法監(jiān)聽(tīng)數(shù)組長(zhǎng)度的變化,導(dǎo)致 vue 不得不重寫(xiě)數(shù)組方法

即便如此,由于改變數(shù)組內(nèi)容的方式實(shí)在有點(diǎn)多,要把數(shù)組設(shè)計(jì)成響應(yīng)式數(shù)據(jù)反而會(huì)導(dǎo)致更多的性能損耗。因此 Vue 不得不提供更多的其他的方式來(lái)監(jiān)聽(tīng)數(shù)組的變化。

比如 forceUpdate,比如大量的 Watcher,還有性能損耗更嚴(yán)重的 Deep Watcher。

另一個(gè)問(wèn)題就是數(shù)據(jù)的層級(jí)與變化問(wèn)題。

數(shù)據(jù)層級(jí)越深,我們想要深度監(jiān)聽(tīng),就得使用遞歸的方式。當(dāng)數(shù)據(jù)發(fā)生變化時(shí),部分?jǐn)?shù)據(jù)與 UI 的綁定關(guān)系需要重新建立「在 vue 中,就是重復(fù)依賴收集的過(guò)程」,如果數(shù)據(jù)量過(guò)大,或者數(shù)據(jù)變化頻繁,就會(huì)有性能風(fēng)險(xiǎn)。

因此 vue 官方文檔也會(huì)建議大家簡(jiǎn)化數(shù)據(jù)層級(jí),減少深度監(jiān)聽(tīng)的成本。

基于這兩個(gè)原因,導(dǎo)致了 vue1.x 的時(shí)候,不敢過(guò)于大聲宣稱自己性能更好。

為什么我要說(shuō) React 的解決方案是一種創(chuàng)新呢?

原因是他打破了傳統(tǒng)的雙向綁定監(jiān)聽(tīng)數(shù)據(jù)的思路,放棄關(guān)注數(shù)據(jù),從而繞開(kāi)了上面的問(wèn)題。

react 把所有的精力都放在了 UI 層。使用我們現(xiàn)在熟知的 diff 算法,當(dāng)數(shù)據(jù)發(fā)生變化時(shí),react 會(huì)創(chuàng)建一個(gè)新的虛擬DOM樹(shù),與之前的樹(shù)做對(duì)比,找出需要改變的元素。

這樣的好處就是完美繞開(kāi)了所有的數(shù)據(jù)類型、數(shù)據(jù)復(fù)雜度、依賴收集等一系列問(wèn)題,react 不僅不用頭疼某些類型監(jiān)聽(tīng)不到,也不需要擔(dān)心數(shù)據(jù)量太大導(dǎo)致更多的性能問(wèn)題。

因此在 vue2.x 的版本中,也部分借鑒了虛擬DOM的解題思路來(lái)緩解 1.x 在數(shù)據(jù)側(cè)的壓力。

從總體思路上來(lái)說(shuō),vue 的主要壓力在于處理數(shù)據(jù),react 的主要壓力在于處理 UI。

react 不建立數(shù)據(jù)與 UI 的對(duì)應(yīng)關(guān)系,那么也就意味著另外一個(gè)壓力的產(chǎn)生,那就是當(dāng)數(shù)據(jù)發(fā)生變化時(shí),react 并不知道哪一個(gè) UI 發(fā)生了變化,于此同時(shí) react 為了保持自己對(duì)于 JavaScript 的弱侵入性,也沒(méi)有在 setState 上進(jìn)行任何魔改,例如綁定當(dāng)前上下文從而得知具體哪個(gè)組件的 state 發(fā)生了變化。

如果進(jìn)行了這個(gè)魔改,diff 的壓力會(huì)小一些。

因此,每一次的 state 變化,都是整棵 DOM 樹(shù)的 diff,這也成為了現(xiàn)在其他框架在輿論宣傳上攻擊 react 性能不好的重要手段和依據(jù),也是許多人覺(jué)得 react 必將被取代的重要原因。

從解決方案來(lái)說(shuō),雙向綁定方案「例如 vue,solid」的努力方向,在于如何降低數(shù)據(jù)側(cè)的性能壓力。

而 react 的努力方向,在于如何減少 UI diff 的性能壓力。

Solid 的底氣在哪?

后來(lái) Vue3 宣傳自己性能高于 react 的聲音逐漸開(kāi)始大起來(lái)了。原因就在于 Proxy 的出現(xiàn)。

defineProperty 在監(jiān)聽(tīng)數(shù)據(jù)上有不少缺陷,因此基于此來(lái)實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)壓力確實(shí)很大,也會(huì)給使用者在數(shù)據(jù)側(cè)帶來(lái)不小的心智負(fù)擔(dān)。而 Proxy 在很大程度上解決了這個(gè)問(wèn)題。

Proxy 能夠監(jiān)聽(tīng)數(shù)組的變化,能夠監(jiān)聽(tīng)刪除對(duì)象字段的變化... 于是 Vue3 的底層實(shí)現(xiàn),在數(shù)據(jù)側(cè)的代碼會(huì)簡(jiǎn)潔很多,并且與此同時(shí),Vue 的后續(xù)版本,也可以徹底放棄虛擬 DOM 來(lái)進(jìn)一步提高自己的運(yùn)行性能。

因此,基于 Proxy 來(lái)實(shí)現(xiàn)雙向綁定成為了許多框架的選擇。這也使得許多框架有了冒頭的理由和機(jī)會(huì),Solid 的底氣也來(lái)自于此。

但是,依然有一個(gè)問(wèn)題沒(méi)有解決。

那就是深度監(jiān)聽(tīng)仍然需要遞歸。當(dāng)數(shù)據(jù)量很大的時(shí)候,依賴追蹤的壓力也會(huì)逐漸變大。

當(dāng)你的項(xiàng)目比較輕量的時(shí)候,你能夠獲得很強(qiáng)的性能體驗(yàn)。但是當(dāng)你的項(xiàng)目變得越來(lái)越大,全局?jǐn)?shù)據(jù)變得越來(lái)越復(fù)雜,層級(jí)越來(lái)越深,他的性能壓力也會(huì)逐漸變大。

當(dāng)然,通常情況下,我們的大多數(shù)項(xiàng)目也達(dá)不到這個(gè)級(jí)別。

React 項(xiàng)目的性能表現(xiàn)

React 的性能壓力主要來(lái)源于 UI 側(cè)的 diff。

當(dāng)項(xiàng)目變得越來(lái)越大,全局狀態(tài)里的數(shù)據(jù)越來(lái)越復(fù)雜。UI 側(cè)的 diff 壓力會(huì)越變?cè)酱髥幔?/p>

答案是:不會(huì)。

這是一個(gè)很有意思的思考。假如我有一個(gè)超大型的項(xiàng)目,一共有 3000 個(gè)頁(yè)面,似乎從理論的角度來(lái)說(shuō),UI diff 的壓力也會(huì)增加到 3000 個(gè)頁(yè)面的量級(jí),但是事實(shí)上我們永遠(yuǎn)只會(huì)在可視區(qū)域里展示一個(gè)頁(yè)面。也就是說(shuō),就算你的項(xiàng)目體量非常大,但是我們只會(huì)渲染一個(gè)頁(yè)面。

虛擬 DOM 的 diff 壓力,也只會(huì)限制在一個(gè)頁(yè)面的量級(jí),這個(gè)壓力不會(huì)隨著項(xiàng)目體量的增加而增加。這個(gè)前提,實(shí)際上就已經(jīng)表明了 React 的性能不會(huì)差到哪里去。

因此在實(shí)踐中,其實(shí)我們也不太需要過(guò)多的關(guān)注 react 的性能問(wèn)題,哪怕是在 Fiber 架構(gòu)出來(lái)之前,也不需要過(guò)多的關(guān)注。

而有意思的是,在許多文章中為了體現(xiàn) solid.js 擁有巨大的性能優(yōu)勢(shì),往往會(huì)構(gòu)建一個(gè)實(shí)踐中幾乎不存在的場(chǎng)景,例如渲染一萬(wàn)個(gè)數(shù)據(jù)的列表比比誰(shuí)花的時(shí)間更少。

然而事實(shí)上,即使我們不使用任何框架,就用原生 JavaScript 來(lái)渲染一萬(wàn)條數(shù)據(jù),也會(huì)采用虛擬列表的方式進(jìn)行優(yōu)化才能確保相對(duì)流暢不卡頓。

我們一定要明白,任何框架的性能都是不可能突破原生 JavaScript 的。

react 性能瓶頸

高頻率的交互往往會(huì)導(dǎo)致明顯的性能問(wèn)題。

例如表單輸入時(shí),我們期望內(nèi)容的任何變化都有對(duì)應(yīng)的 UI 響應(yīng),實(shí)踐項(xiàng)目中容易出現(xiàn)明顯的卡頓和延遲。常規(guī)的優(yōu)化手段是使用防抖。

當(dāng)然,在 antd 的 Form 組件也使用了將數(shù)據(jù)下放到每一個(gè) Item 的方式來(lái)優(yōu)化性能,store 中用 useRef 存儲(chǔ)數(shù)據(jù)而不是 useState,antd 內(nèi)部為每個(gè) Form.Item 定義了 forceUpdate 來(lái)強(qiáng)制更新 Item UI。

又例如拖拽/resize等事件。此時(shí)我們只需要通過(guò)操作原生 DOM 的方式來(lái)實(shí)現(xiàn)對(duì)應(yīng)的邏輯即可。從而繞開(kāi)高頻率的 diff 邏輯

這些性能瓶頸,大概率在 vue 和 Solid 中,也會(huì)存在。解決問(wèn)題的思路也相差不大。

事實(shí)上,原生 DOM 本身在高頻交互上也存在明顯的性能瓶頸。因此許多前端項(xiàng)目不得不采用拋棄 DOM 渲染的方式來(lái)完成整個(gè)項(xiàng)目。但是這些項(xiàng)目我們?nèi)匀豢梢越Y(jié)合 react 來(lái)完成,例如著名的前端項(xiàng)目 Figma,或者國(guó)內(nèi)有的團(tuán)隊(duì)使用 react + skia 的方式來(lái)完成一些對(duì)性能要求很高的項(xiàng)目。

一個(gè)好的思路是,不要試圖用框架解決所有事情,而是讓他解決他擅長(zhǎng)的事情。

小痛點(diǎn)

在使用 vue 時(shí),我們常常需要警惕對(duì)數(shù)據(jù)進(jìn)行一些操作時(shí),讓數(shù)據(jù)失去響應(yīng)性。在 Solid 中同樣如此。

Solid 的官方文檔案例中有這樣一段代碼。

const CountingComponent = () => {
  const [count, setCount] = createSignal(0);
  
  const interval = setInterval(
  () => setCount(c => c + 1),
  1000
 );
 onCleanup(() => clearInterval(interval));
 
 return <div>Count value is {count()}</div>;
};

當(dāng)我們使用 createSignal 定義了一個(gè)響應(yīng)式數(shù)據(jù)時(shí),此時(shí)返回的 count,并不是一個(gè)數(shù)據(jù),而是一個(gè)獲取數(shù)據(jù)的方法,注意這種差別。

在使用中,我們必須以執(zhí)行該方法的形式來(lái)當(dāng)成數(shù)據(jù)使用。如果 JSX 中有多處使用了該數(shù)據(jù),我們也必須以執(zhí)行該方法的形式來(lái)當(dāng)成數(shù)據(jù)使用,count() 而不是 count。

如果我使用一個(gè)變量來(lái)緩存他的執(zhí)行結(jié)果,然后使用該變量嵌入 JSX 中使用,該數(shù)據(jù)就會(huì)失去響應(yīng)性。

var c = count()

// 失去響應(yīng)性
<div>Count value is {c}</div>;

這里存在的問(wèn)題就是語(yǔ)義與語(yǔ)法的錯(cuò)位,讓我覺(jué)得不太舒服。

vue3 實(shí)際上也存在類似的問(wèn)題,他為了避免這種語(yǔ)義與語(yǔ)法的錯(cuò)位,分別采用了 ref 來(lái)監(jiān)聽(tīng)基礎(chǔ)數(shù)據(jù)類型, reactive 來(lái)監(jiān)聽(tīng)引用數(shù)據(jù)類型,雖然在 ref 的使用上任然需要借助 .value 來(lái)達(dá)到響應(yīng)性,但好在實(shí)踐項(xiàng)目中單獨(dú)把基礎(chǔ)數(shù)據(jù)類型作為響應(yīng)式數(shù)據(jù)的場(chǎng)景非常少。

也就是說(shuō),在解決這個(gè)問(wèn)題上,反而 vue3 比 solid 更加優(yōu)雅,當(dāng)然,即便如此,在 vue3 中,一些操作也會(huì)讓數(shù)據(jù)失去響應(yīng)性,例如解構(gòu),這是我們?cè)趯W(xué)習(xí)的時(shí)候需要特別注意的地方。

react hooks 的痛點(diǎn),閉包。

react 常常因?yàn)殚]包問(wèn)題,被各種攻擊。認(rèn)為這是 react 的缺陷。如果你沒(méi)有掌握好閉包,視閉包為洪水猛獸,你多半也會(huì)認(rèn)同這樣的說(shuō)法。

因?yàn)閺谋憩F(xiàn)結(jié)果上來(lái)看,閉包帶來(lái)的緩存問(wèn)題確實(shí)會(huì)導(dǎo)致使用者在理解上存在很多疑問(wèn)。然而事實(shí)上,閉包問(wèn)題不是 react 的問(wèn)題,而是 JavaScript 本身的特性,閉包是學(xué)習(xí) JavaScript 本應(yīng)該掌握好的基礎(chǔ)之一,只不過(guò)很多前端開(kāi)發(fā)沒(méi)有做到而已。

新人朋友估計(jì)在面試時(shí),也常常被閉包相關(guān)的面試題虐哭 ~

react 提供了一個(gè)實(shí)踐場(chǎng)景,讓我們能夠直面閉包帶來(lái)的困擾,從而對(duì)閉包更加有掌控度,我認(rèn)為這反而應(yīng)該成為 react 的優(yōu)勢(shì)之一,而不是痛點(diǎn)。

但是 vue3 和 solid 都在極力的避免讓開(kāi)發(fā)者感受到閉包的存在,甚至把這種行為當(dāng)成自己的優(yōu)勢(shì)來(lái)大力宣傳,從我個(gè)人的角度來(lái)說(shuō),我并不贊同這樣的觀點(diǎn),因?yàn)槲覀兘K究是要理解并掌握閉包的呀,對(duì)吧。

跨平臺(tái)

Solid 為了極致的性能體驗(yàn),完全棄用了虛擬 DOM,也就意味著,他放棄了跨平臺(tái)的特性。只把主要精力集中在 web 項(xiàng)目上。也就是說(shuō),他的全局生態(tài)建設(shè),永遠(yuǎn)也趕不上 react

到目前為止,React 已經(jīng)把觸手伸向了后端開(kāi)發(fā)... 已經(jīng)不滿足簡(jiǎn)單的服務(wù)端渲染了,甚至還想要連接數(shù)據(jù)庫(kù)...

這也是 Solid 無(wú)法取代 react 最重要的原因。

我們也可以自己擴(kuò)展 react 的生態(tài)。比如在我的 2d 可視化課程中,我們基于 canvas 封裝了一套類 DOM 的渲染引擎,然后接入 react-reconciler,就能輕松得到一個(gè) react-echarts 的圖表組件,在使用層還是 react 組件,但是在底層已經(jīng)被我瞧瞧的把 DOM 換成了 canvas,或者 webGPU... ,此時(shí),我的項(xiàng)目性能,將會(huì)遠(yuǎn)超 Solid.

總結(jié)

雙向綁定是一種傳統(tǒng)的解決方案,與之相對(duì)比,在前端領(lǐng)域 react 的解決方案是一個(gè)巨大的創(chuàng)新。單向數(shù)據(jù)流,Diff算法,雙緩存策略,優(yōu)先級(jí)隊(duì)列,任務(wù)中斷,瀏覽器空閑時(shí)間,并發(fā),函數(shù)式編程,自定義hook... 等等許多概念都極大的擴(kuò)展了前端開(kāi)發(fā)的技術(shù)視野。

并不確定 react 是否借鑒了其他領(lǐng)域的方案,認(rèn)真看過(guò)我 JavaScript 核心進(jìn)階的同學(xué)就應(yīng)該知道,F(xiàn)iber 架構(gòu)在很大程度上借鑒了 V8 垃圾回收的底層機(jī)制。

而 Solid 作為模仿者,與 React 相比,他并沒(méi)有什么突出的優(yōu)勢(shì),也沒(méi)有什么技術(shù)和理念上的創(chuàng)新。他只是滿足了部分前端開(kāi)發(fā)對(duì)于雙向綁定 + 函數(shù)式的美好愿景而已,至于 vue 和 angular 最終都會(huì)采用 Signal 重構(gòu)底層代碼,那只不過(guò)是因?yàn)樗麄儽旧韽囊婚_(kāi)始就是雙向綁定的基因。

因此在做技術(shù)選型時(shí),任何一個(gè)成熟的前端架構(gòu)師都沒(méi)有理由放棄 react 而選擇 Solid,無(wú)論是從性能上考慮,還是從生態(tài)上考慮,理由都不夠充分,F(xiàn)lutter 尚且做不到取締 React Native,Solid 要走的路還很長(zhǎng)。

而有的人寫(xiě)文章聲稱 Solid 比 React 還 React,Solid 教 React 寫(xiě)函數(shù)式,降維打擊... 那只是常規(guī)的宣傳用語(yǔ),當(dāng)不得真。

責(zé)任編輯:姜華 來(lái)源: 這波能反殺
相關(guān)推薦

2016-03-17 09:45:17

react雙向綁定插件

2024-06-07 08:33:54

2021-09-07 18:40:55

單向數(shù)據(jù)流數(shù)據(jù)

2022-08-22 09:01:24

Vue響應(yīng)式原則雙向數(shù)據(jù)綁定

2016-11-02 12:47:51

數(shù)據(jù)流動(dòng)大數(shù)據(jù)

2018-10-07 23:03:22

數(shù)據(jù)應(yīng)用Web

2017-03-10 10:25:17

2015-08-20 14:29:38

Docker虛擬機(jī)

2021-04-21 14:22:08

前端開(kāi)發(fā)技術(shù)

2011-12-14 15:57:13

javanio

2009-08-19 10:41:12

Java輸入數(shù)據(jù)流

2022-03-18 08:57:17

前端數(shù)據(jù)流選型

2022-07-15 09:01:15

React對(duì)象編程

2011-03-09 10:20:18

云計(jì)算企業(yè)通信

2024-05-10 08:44:25

ChatGPT模型GPT

2021-12-26 23:04:34

機(jī)器人人工智能技術(shù)

2017-10-27 22:03:35

javascrip

2015-08-20 10:31:55

DockerLinux開(kāi)源

2016-11-14 19:01:36

數(shù)據(jù)流聊天系統(tǒng)web

2019-02-26 13:53:07

PythonJava編程語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人午夜免费网站 | 天天干夜夜操 | 成人av鲁丝片一区二区小说 | 日韩精品中文字幕一区二区三区 | 国产区在线观看 | 日韩在线一区二区 | 2019天天干夜夜操 | 91一区二区 | 中文字幕av一区 | 免费高清成人 | 日韩av中文 | 欧美在线色视频 | 久久久久久久久国产精品 | 久久精品视频99 | 久久久久久高潮国产精品视 | 久久久久国产 | 在线免费激情视频 | 欧美一区二区三区在线观看 | 欧美精品一区二区三区一线天视频 | 福利视频网站 | 国产一区二区中文字幕 | 一级黄色大片 | 男人的天堂久久 | 男人的天堂久久 | 国产精品久久久久永久免费观看 | 91精品国产91久久综合桃花 | 国产高清视频一区二区 | 欧美高清一区 | 色综合美女 | 仙人掌旅馆在线观看 | 日韩二 | 日本一二区视频 | 亚洲第一区久久 | 伊人伊成久久人综合网站 | 国产亚洲精品精品国产亚洲综合 | 97久久国产| 午夜精品久久久久久久星辰影院 | 国产一区精品在线 | 亚洲精品68久久久一区 | 国产精品爱久久久久久久 | 日韩一区二区在线视频 |