Svelte跨組件狀態(tài)管理

svelte中對(duì)于組件內(nèi)的狀態(tài)管理比較簡(jiǎn)單,但是如何像其它框架一樣進(jìn)行跨組件間交互呢?

利用props進(jìn)行狀態(tài)傳遞

我們首先通過(guò)官網(wǎng)APi可以了解到和其它框架一樣的傳遞策略,它們使用props傳遞狀態(tài),從而進(jìn)行交互。

當(dāng)一個(gè)組件需要與另一個(gè)組件共享數(shù)據(jù)時(shí),可以在組件樹中將狀態(tài)上移,直到這些組件有了一個(gè)公共父級(jí)。

需要向下傳遞狀態(tài),直到到達(dá)需要此狀態(tài)信息的所有組件為止。

這是使用props完成的,并且我認(rèn)為這是一種最好的技術(shù),因?yàn)樗芎?jiǎn)單。

Context API

在某些情況下props不實(shí)用。 例如在組件樹中,兩個(gè)組件之間的距離相當(dāng)遠(yuǎn)遙,以至于我們不得不將狀態(tài)提升到頂級(jí)組件。

這種情況下可以使用另一種技,它稱為Context,當(dāng)您希望讓多個(gè)組件與后代進(jìn)行通信,但又不希望到處傳遞props時(shí),這是一種很好的方法。

在Context中設(shè)置對(duì)象,并將其與鍵關(guān)聯(lián):

<script>
import { setContext } from 'svelte'

const someObject = {}

setContext('someKey', someObject)
</script>

在另一個(gè)組件中,可以使用getContext檢索分配給鍵的對(duì)象

<script>
import { getContext } from 'svelte'

const someObject = getContext('someKey')
</script>

注意:您只能在使用setContext的組件中或者它的后代中使用getContext來(lái)檢索數(shù)據(jù)。

如果您想讓位于2個(gè)不同組件樹中的兩個(gè)組件進(jìn)行通信,那么還有另一種方式供我們使用:stores。

Svelte stores

當(dāng)組件需要相互通信而不需要傳遞太多的props時(shí),Svelte stores是處理應(yīng)用程序狀態(tài)的好方式。

首先我們需要導(dǎo)入從svelte/store導(dǎo)入writable:

import { writable } from 'svelte/store'

使用writable()函數(shù)創(chuàng)建存儲(chǔ)變量,并將默認(rèn)值作為第一個(gè)參數(shù)傳遞.

const username = writable('Guest')

它可以放在一個(gè)單獨(dú)的文件中,您可以將其導(dǎo)入多個(gè)組件,例如store.js。

import { writable } from 'svelte/store'
export const username = writable('Guest')

現(xiàn)在加載此文件的任何其他組件都可以訪問(wèn)存儲(chǔ)

<script>
import { username } from './store.js'
</script>

現(xiàn)在,可以使用set()將這個(gè)變量的值設(shè)置為一個(gè)新值,并將新值作為第一個(gè)參數(shù)傳遞

username.set('new username')

它可以使用update()函數(shù)進(jìn)行更新,這與set()不同,因?yàn)槟恢皇菍⑿轮祩鬟f給它—而是運(yùn)行一個(gè)將當(dāng)前值作為參數(shù)傳遞的回調(diào)函數(shù)。

const newUsername = 'new username!'
username.update(existing => newUsername)

你可以在這里添加更多的邏輯

username.update(existing => {
  console.log(`Updating username from ${existing} to ${newUsername}`)
  return newUsername
})

如果想要獲取一次store的值,我們可以使用從svelte/store導(dǎo)入的get()方法。

import { readable, get } from 'svelte/store'
export const username = writable('Guest')
get(username) //'Guest'

相反,要?jiǎng)?chuàng)建一個(gè)響應(yīng)性的變量(每當(dāng)它更改時(shí)就更新),可以使用(在本例中為username)預(yù)先設(shè)置store變量。使用它將使組件在存儲(chǔ)值發(fā)生更改時(shí)重新運(yùn)行。

Svelte把$作為一個(gè)保留值,將阻止您將它用于與存儲(chǔ)值無(wú)關(guān)的內(nèi)容(這可能會(huì)導(dǎo)致混淆),因此,如果您使用$來(lái)預(yù)先當(dāng)做DOM引用,那么不要在Svelte中這樣做。另一種選擇是使用username的subscribe()方法,如果需要在變量更改時(shí)執(zhí)行某些邏輯,這是最適合的方式。

username.subscribe(newValue => {
    console.log(newValue)
})

了writable stores之外,Svelte還提供了兩種特殊類型的存儲(chǔ):readable storesderived stores.

Svelte Readable Stores

Readable stores之所以特別,是因?yàn)樗鼈儫o(wú)法從外部進(jìn)行更新-沒(méi)有set()或update()方法。 相反,一旦設(shè)置了初始狀態(tài),便無(wú)法從外部進(jìn)行修改。

官方的Svelte文檔展示了一個(gè)有趣的使用計(jì)時(shí)器更新日期的例子。我可以考慮設(shè)置一個(gè)計(jì)時(shí)器來(lái)從網(wǎng)絡(luò)獲取資源、執(zhí)行API調(diào)用、從文件系統(tǒng)獲取數(shù)據(jù)(使用本地Node.js服務(wù)器)或其他任何可以自主設(shè)置的東西。

在本例中,我們沒(méi)有使用writable()來(lái)初始化存儲(chǔ)變量,而是使用了readable().

import { readable } from 'svelte/store'
export const count = readable(0)

您可以在默認(rèn)值之后提供一個(gè)函數(shù),該函數(shù)將負(fù)責(zé)更新它。這個(gè)函數(shù)接收set函數(shù)來(lái)修改值

<script>
import { readable } from 'svelte/store'
export const count = readable(0, set => {
  setTimeout(() => {
    set(1)
  }, 1000)
})
</script>

在本例中,我們?cè)?秒后將值從0更新為1。

你也可以在這個(gè)函數(shù)中設(shè)置一個(gè)區(qū)間:

import { readable, get } from 'svelte/store'
export const count = readable(0, set => {
  setInterval(() => {
      set(get(count) + 1)
  }, 1000)
})

您可以在另一個(gè)類似的組件中使用它:

<script>
import { count } from './store.js'
</script>

{$count}

Svelte Derived Stores

derived store允許您創(chuàng)建依賴于現(xiàn)有存儲(chǔ)的值的新存儲(chǔ)值。

您可以使用svelte/store導(dǎo)出的derived store來(lái)實(shí)現(xiàn)此目的,它以現(xiàn)有存儲(chǔ)值作為第一個(gè)參數(shù),以函數(shù)作為第二參數(shù),該函數(shù)接收該存儲(chǔ)值作為其第一個(gè)參數(shù):

import { writable, derived } from 'svelte/store'

export const username = writable('Guest')

export const welcomeMessage = derived(username, $username => {
  return `Welcome ${$username}`
})
<script>
import { username, welcomeMessage } from './store.js'
</script>

{$username}
{$welcomeMessage}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作為一個(gè)合格的開發(fā)者,不要只滿足于編寫了可以運(yùn)行的代碼。而要了解代碼背后的工作原理;不要只滿足于自己的程序...
    六個(gè)周閱讀 8,686評(píng)論 1 33
  • 在前一章中我們已經(jīng)感受到完全用React來(lái)管理應(yīng)用數(shù)據(jù)的麻煩,在這一章中,我們將介紹Redux這種管理應(yīng)用...
    六個(gè)周閱讀 1,094評(píng)論 0 8
  • 很感謝https://segmentfault.com/u/cwl提供的答案React 組件間通訊 說(shuō) React...
    喵嗚Yuri閱讀 988評(píng)論 0 2
  • 其實(shí)之所以講到這里是因?yàn)?當(dāng)我們使用React的組件化開發(fā)Web應(yīng)用的時(shí)候,就會(huì)遇到這樣的問(wèn)題,很多組件需要某個(gè)功...
    井潤(rùn)閱讀 481評(píng)論 0 0
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí),對(duì)React的特性、重點(diǎn)和注意事項(xiàng)的提取、精練和總結(jié),可以做為React特性...
    科研者閱讀 8,424評(píng)論 2 21

友情鏈接更多精彩內(nèi)容