Svelte?和?React的比較詳解(一)
比較 Svelte 和 React
在這篇文章中,我將告訴您我更喜歡 Svelte 還是 React,不能以個(gè)人意見(jiàn)代表誰(shuí)好誰(shuí)壞。以及我發(fā)現(xiàn)使用這兩個(gè)框架的一些區(qū)別。
驗(yàn)證
在 React 中創(chuàng)建了一個(gè) useCurrentUser
的鉤子,用于偵聽(tīng)身份驗(yàn)證更改并相應(yīng)地設(shè)置一些狀態(tài)。然后我可以在 React 任何地方使用,并在身份驗(yàn)證更改時(shí)重新渲染頁(yè)面。
export const useCurrentUser = () => { const [currentUser, setCurrentUser] = useState(undefined) useEffect(() => { return firebase.auth().onAuthStateChanged((details) => { setCurrentUser( details ? { displayName: details.displayName, provider: { 'github.com': 'GitHub', }[details.providerData[0].providerId], uid: details.uid, } : null ) }) }, []) return [currentUser] }
在任何組件中,都可以使用:
const [currentUser] = useCurrentUser()
這可以讓任何組件快速獲取當(dāng)前用戶(hù)。唯一的缺點(diǎn)是在每一個(gè)頁(yè)面都有一個(gè) onAuthStateChanged
監(jiān)聽(tīng)器,
但可以通過(guò)僅綁定一個(gè)偵聽(tīng)器或?qū)?dāng)前用戶(hù)置于執(zhí)行上下文中來(lái)解決。
執(zhí)行上下文,在 Svelte 中可以采用的方法并使用可寫(xiě)存儲(chǔ)。
export const currentUser = writable() export const listenForAuthChanges = () => { return firebase.auth().onAuthStateChanged((details) => { if (details) { currentUser.set({ displayName: details.displayName, provider: { 'github.com': 'GitHub', }[details.providerData[0].providerId], uid: details.uid, }) } else { currentUser.set(null) } }) }
在頂級(jí) Svelte 組件中,我可以在 onMount
中調(diào)用它,它將在掛載組件時(shí)執(zhí)行(該函數(shù)是 return
編輯的,因此我們?cè)趧h除組件時(shí)取消訂閱,就像 useEffect
讓你返回一個(gè)函數(shù)銷(xiāo)毀)。
onMount(() => { return listenForAuthChanges() })
這樣在 Svelte 代碼庫(kù)中的任何地方,組件都可以導(dǎo)入 currentUser
可寫(xiě)存儲(chǔ)。您可以訂閱它并手動(dòng)控制狀態(tài)更改:
currentUser.subscribe(newValue => { ... })
或者,如果你想讀取最新的值:
console.log($currentUser)
這就是 Svelte 的語(yǔ)法技巧厲害的地方;這個(gè)$
前綴會(huì)獲取最新的值。
雖然對(duì)于初學(xué)者來(lái)說(shuō)有點(diǎn)奇怪。但是,Svelte 就省去調(diào)用 subscribe
的API。
就基本身份驗(yàn)證而言,兩個(gè)庫(kù)似乎都采用了類(lèi)似的方法。雖然確切語(yǔ)法略有不同,但兩者都允許您訂閱 Firebase 偵聽(tīng)器并在身份驗(yàn)證狀態(tài)更改時(shí)獲得更新。
從使用者角度開(kāi)發(fā)
Pomodone 是一個(gè) 25 分鐘的計(jì)時(shí)器,并盡可能準(zhǔn)確。如果瀏覽器選項(xiàng)卡處于后臺(tái)(不是焦點(diǎn)選項(xiàng)卡),大多數(shù)瀏覽器將降低其 setTimeout
調(diào)用的優(yōu)先級(jí)并且不會(huì)嚴(yán)格按時(shí)運(yùn)行它們。大多數(shù)時(shí)候在網(wǎng)絡(luò)上這不是什么大不了的事,但是當(dāng)用戶(hù)通過(guò)您的應(yīng)用程序跟蹤 25 分鐘的工作時(shí),它就有問(wèn)題,在 25 分鐘的過(guò)程中,任何輕微的時(shí)間漂移都會(huì)導(dǎo)致最終時(shí)間相差甚遠(yuǎn)。但是,如果將這些超時(shí)轉(zhuǎn)移到 Web Worker 中,它們應(yīng)該會(huì)按時(shí)運(yùn)行,并且不會(huì)被瀏覽器取消優(yōu)先級(jí)。
因此,在我的 Tracker
組件中,我需要實(shí)例化一個(gè) Web Worker,向它發(fā)送消息并接收數(shù)據(jù)(例如剩余時(shí)間)。這時(shí)我發(fā)現(xiàn) React 比 Svelte 更重管理的一個(gè)領(lǐng)域;
因?yàn)?React 組件在每次重新渲染時(shí)都會(huì)重新執(zhí)行,所以很容易導(dǎo)致創(chuàng)建數(shù)千個(gè) worker!必須使用 useRef 通過(guò)維護(hù)對(duì)您創(chuàng)建的工作程序的引用來(lái)避免此問(wèn)題。
首先,我設(shè)置了組件所需的初始狀態(tài):
const [currentPom, setCurrentPom] = useState(null) const [currentUser] = useCurrentUser() const worker = useRef(null)
然后創(chuàng)建一個(gè) useEffect
掛鉤,如果需要,它將實(shí)例化 worker,并綁定一個(gè)事件監(jiān)聽(tīng)器來(lái)監(jiān)聽(tīng)消息:
useEffect(() => { if (!worker.current) { worker.current = new Worker(workerURL) window.worker = worker.current } const onMessage = (event) => { if (event.data.name === 'tick') { setCurrentPom((currentPom) => ({ ...currentPom, secondsRemaining: event.data.counter, })) } else if (event.data.name === 'start') { // More branches removed here to save space... } } worker.current.addEventListener('message', onMessage) return () => { worker.current.removeEventListener('message', onMessage) } }, [currentUser])
然后,當(dāng)用戶(hù)點(diǎn)擊“開(kāi)始”按鈕時(shí),我必須向 worker 發(fā)送一條消息:
const onStartPom = () => { if (!worker.current) return worker.current.postMessage('startTimer') }
Svelte 看起來(lái)非常相似,但在我看來(lái)有兩個(gè)小的變化使 Svelte 代碼更易于閱讀:
- 我們不必將 worker 保留在
useRef
中,只需將其分配給一個(gè)變量即可。 - 我們可以更輕松地將事件偵聽(tīng)器代碼拉出到一個(gè)函數(shù)中,因?yàn)樵摵瘮?shù)不會(huì)成為
useEffect
的依賴(lài)項(xiàng)——此時(shí)我們必須將它包裝在useCallback
中。
let worker onMount(() => { worker = new Worker(workerURL) worker.addEventListener('message', onWorkerMessage) return () => { worker.removeEventListener('message', onWorkerMessage) } })
我們也不必使用 React 的 setX(oldX => newX)
約定來(lái)設(shè)置狀態(tài),只需改變局部變量即可:
function onWorkerMessage(event) { if (event.data.name === 'tick') { currentPom = { ...currentPom, secondsRemaining: event.data.counter, } } else if (event.data.name === 'start') { // More branches here removed to save space... } }
這就是 Svelte 好的地方;兩者非常相似,但是一旦習(xí)慣 Svelte, 感覺(jué)React就像在跳圈。你不能創(chuàng)建一個(gè)工作實(shí)例,它必須進(jìn)入 useRef
,然后你不能輕易地將代碼拉出到一個(gè)函數(shù)中而不需要 useCallback
所以它可以是對(duì) useEffect
的安全依賴(lài)。
使用 Svelte,我編寫(xiě)的代碼更接近于“純”JavaScript,而在 React 中,我的更多代碼被包裝在 React 原語(yǔ)中。
條件渲染
React 它只是 JavaScript。與 Svelte 的模板語(yǔ)言相比, React 中你不使用獨(dú)特的模板語(yǔ)法而是在編寫(xiě) JavaScript:
SideTabs
<ul> {pomsForCurrentDay.map(entryData, index) => { const finishedAt = format(new Date(entryData.timeFinished), 'H:mm:ss') return <li title={`Finished at ${finishedAt}`}>{index + 1}</li> })} </ul>
在過(guò)去,我發(fā)現(xiàn)模板語(yǔ)言是趨勢(shì)但不靈活,但 Svelte 提供了恰到好處的模板,同時(shí)也使您能夠使用 JavaScript。也就是說(shuō),我總是會(huì)發(fā)現(xiàn) React 的方法更簡(jiǎn)單 - 至少在我的腦海中 - 我認(rèn)為對(duì)于熟悉 JavaScript 并正在學(xué)習(xí)庫(kù)的人來(lái)說(shuō)更友好。
然而,在渲染組件時(shí),Svelte 確實(shí)對(duì)其語(yǔ)法進(jìn)行了一些不錯(cuò)的修改(感覺(jué)非常像 JSX)。我最喜歡的是折疊道具的能力:
<History pomodoros={pomodoros} />
Svelte (collapsed props)
<History {pomodoros}/>
到此這篇關(guān)于Svelte 和 React的比較詳解(一)的文章就介紹到這了,更多相關(guān)Svelte 和 React比較內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js遍歷、動(dòng)態(tài)的添加數(shù)據(jù)的小例子
js遍歷、動(dòng)態(tài)的添加數(shù)據(jù)的小例子,需要的朋友可以參考一下2013-06-06JS在可編輯的div中的光標(biāo)位置插入內(nèi)容的方法
這篇文章主要介紹了JS在可編輯的div中的光標(biāo)位置插入內(nèi)容的方法,分別用js與jQuery兩種方式加以實(shí)現(xiàn),是非常實(shí)用的特效技巧,需要的朋友可以參考下2014-11-11JavaScript中Cookie的使用之如何設(shè)置失效時(shí)間
這篇文章主要介紹了JavaScript中Cookie的使用之如何設(shè)置失效時(shí)間問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-12-12原生JS中應(yīng)該禁止出現(xiàn)的寫(xiě)法
這篇文章主要介紹了原生JS中應(yīng)該禁止出現(xiàn)的寫(xiě)法,以提高代碼效率和安全性,對(duì)效率和安全感興趣的同學(xué),可以參考下2021-05-05JavaScript異步隊(duì)列進(jìn)行try?catch時(shí)的問(wèn)題解決
這篇文章主要介紹了JavaScript異步隊(duì)列進(jìn)行try?catch時(shí)的問(wèn)題解決,文章圍繞主題展開(kāi)詳細(xì)的的相關(guān)內(nèi)容介紹,需要的朋友可以參考一下2022-07-07如何利用moment處理時(shí)間戳并計(jì)算時(shí)間的差值
前端很多場(chǎng)景都會(huì)涉及到對(duì)時(shí)間的處理,我所用得最多的庫(kù)是moment,下面這篇文章主要給大家介紹了關(guān)于如何利用moment處理時(shí)間戳并計(jì)算時(shí)間的差值的相關(guān)資料,需要的朋友可以參考下2022-04-04微信小程序uploadFile接口實(shí)現(xiàn)文件上傳
這篇文章主要介紹了微信小程序uploadFile接口實(shí)現(xiàn)文件上傳流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08