與Xstate協調Svelte動畫
Mar 25, 2025 am 09:35 AM這篇文章是對Xstate的介紹,因為它可以在Svelte項目中使用。 Xstate在JavaScript生態系統中是獨一無二的。它不會使您的DOM與應用程序狀態同步,但是它可以通過允許您將其建模為有限狀態機(FSM)來幫助管理您的應用程序狀態。
深入了解國家機器和形式語言的範圍超出了這篇文章的範圍,但喬恩·貝拉(Jon Bellah)在另一篇CSS-Tricks文章中做到了這一點。現在,將FSM視為流程圖。流程圖具有多種狀態,表示為氣泡,並且從一個狀態到下一個狀態的箭頭表示從一個狀態到下一個狀態的過渡。國家機器可以擁有一個以上的箭頭,如果是最終狀態,則根本沒有一個箭頭,甚至可以使箭頭離開狀態,並立即指向同一狀態。
如果所有這些聽起來都不知所措,那麼放鬆,我們將詳細介紹所有細節,又慢。目前,高級視圖是,當我們將應用程序建模為狀態機器時,我們將創建不同的“狀態”,我們的應用程序可以進入(獲取它…狀態機……狀態……狀態?),發生並導致狀態更改的事件將是這些狀態之間的箭頭。 XSTATE稱這些國家為“狀態”,而各州之間的箭頭為“行動”。
我們的例子
Xstate具有學習曲線,這使教學具有挑戰性。過於人為的用例,它看起來將是不必要的複雜。只有當應用程序的代碼有些糾結時,Xstate才會發光。這使得它很棘手。話雖如此,我們將要查看的示例是一個自動完成的小部件(有時稱為AutoSuggest),或一個輸入框,當單擊時,它會揭示一個要選擇的項目列表,即在輸入中輸入時過濾器。
在這篇文章中,我們將考慮清理動畫代碼。這是起點:
這是我苗條的館庫中的實際代碼,儘管此帖子已刪除了不必要的作品。您可以單擊輸入並過濾項目,但是您將無法選擇任何內容,通過項目,懸停等。我刪除了與此帖子無關的所有代碼。
我們將查看項目列表的動畫。當您單擊輸入時,結果列表首先渲染時,我們希望將其放下動畫。當您鍵入和過濾時,對列表的尺寸的更改將使越來越小的動畫。當輸入失去焦點時,或者您單擊ESC時,我們將列表的高度動畫為零,同時將其褪色,然後將其從DOM(而不是之前)刪除。為了使事情變得更有趣(對用戶來說很好),讓我們使用與我們用於關閉的彈簧配置不同的彈簧配置,因此列表更快或僵硬地關閉了一點,因此不需要的UX不會在屏幕上徘徊太久。
如果您想知道為什麼我不使用Svelte Transition來管理DOM內外動畫,那是因為我還為列表打開時的尺寸,作為用戶過濾時,在過渡之間進行協調,而常規的彈簧動畫在從DOM中刪除元素之前要恢復元素要零要困難得多。例如,如果用戶快速鍵入並過濾列表,則會發生什麼?正如我們將看到的那樣,Xstate可以輕鬆地進行棘手的狀態過渡。
解決問題
到目前為止,讓我們看一下示例的代碼。當列表打開時,我們有一個開放變量可以控制,以及一個可控制列表是否應在DOM中的屬性。我們還擁有一個閉合變量,可以控制列表是否在關閉過程中。
在第28行上,當輸入單擊或集中時,有一個輸入式方法。現在,讓我們注意,它設置為“ true”和“結果”。當用戶在輸入中鍵入輸入並將其設置為true時,請調用輸入變化。這是為了集中輸入時,用戶單擊逃脫以關閉它,但然後開始鍵入,以便重新打開。而且,當然,當您期望時,輸入布雷德函數會運行,並設置為true並開放為false。
讓我們挑選出這種糾結的混亂,看看動畫的工作原理。請注意頂部的slideinspring和不透明度。前者上下滑動列表,並將大小調整為用戶類型。隱藏時,後者逐漸消失。我們將主要關注Slideinspring。
看看稱為setSpringDimensions的函數的怪異。這更新了我們的幻燈片彈簧。為了關注重要作品,我們採用了一些布爾屬性。如果列表正在打開,我們設置了開放式彈簧配置,我們立即通過{Hard:true}配置來設置列表的寬度(我希望列表僅滑下而不是向下滑動),然後設置高度。如果我們要關閉,我們將動畫至零,並且,當動畫完成時,我們將resuctlistlistvissvissvission設置為false(如果關閉動畫被中斷,那麼Svelte將足夠聰明,以至於無法解決承諾,以免回調)。最後,此方法也隨時稱為結果列表的大小更改,即作為用戶過濾。我們在其他地方設置了一個調節器來管理此操作。
意大利麵條
讓我們盤點此代碼。
- 我們的開放變量可以跟踪列表是否打開。
- 我們有resultListVisible變量,該變量跟踪列表是否應在DOM中(並在完成密閉動畫完成後設置為False)。
- 我們具有關閉變量,該變量是否在關閉過程中進行跟踪,我們會在輸入焦點/點擊處理程序中檢查該列表,以便如果用戶在完成之前迅速重新啟用了窗口小部件,我們可以逆轉關閉動畫。
- 我們還有setspringDimensions,我們在四個不同的地方稱呼。它根據列表打開,關閉還是僅在打開時調整大小的列表(即用戶過濾列表)設置我們的彈簧。
- 最後,當結果列表dom元素呈現時,我們有一個結果效果的svelte動作。它啟動了我們的resizeObserver,當dom節點卸下時,將關閉為false。
你抓了這個錯誤嗎?按下ESC按鈕時,我只設置為false。我忘了設置為true,並調用setSpringDimensions(false,true)。此博客文章沒有故意人造這個錯誤!這是我對這個小部件動畫進行大修時犯的實際錯誤。我可以將輸入中的代碼粘貼到捕獲逃生按鈕的位置,甚至將其移至新功能並從兩個地方調用它。該錯誤在根本上並不難解決,但確實會增加代碼的認知負載。
我們要跟踪很多事情,但是最糟糕的是,這種狀態散佈在整個模塊中。採用上面描述的任何狀態,並使用Codesandbox的查找功能來查看使用該狀態的所有位置。您會看到光標在文件上彈跳。現在,想像一下您是該代碼的新手,試圖理解它。考慮一下您必須跟踪所有這些狀態作品的心理模型的日益增長的心理模型,根據其存在的所有位置來弄清楚它的工作原理。我們都去過那裡;很爛。 Xstate提供了更好的方法;讓我們看看如何。
介紹Xstate
讓我們退後一步。在用戶互動時發生的事件發生,導致副作用以及向新狀態的過渡時,事件發生的事件發生,對我們的小部件進行建模是否會更簡單?當然,但這就是我們已經在做的事情;問題是,代碼無處不在。 Xstate使我們能夠以這種方式正確建模我們的狀態。
設定期望
不要指望Xstate神奇地使我們的所有復雜性消失。我們仍然需要協調我們的彈簧,根據打開和關閉狀態調整彈簧配置,句柄尺寸等。 XSTATE給我們的是能夠以易於推理和調整的方式集中該狀態管理代碼。實際上,由於我們的狀態機器設置,我們的總體數量將有所增加。讓我們看看。
您的第一台現狀機器
讓我們直接跳入,看看裸露的骨骼狀態機的外觀。我正在使用XSTATE的FSM軟件包,這是一個最小的XSTATE版本,具有很小的1KB捆綁包大小,非常適合圖書館(例如AutoSoggest Widget)。它沒有太多的高級功能,例如完整的Xstate軟件包,但是我們不需要它們來使用它們,並且我們不希望它們像這樣的介紹性帖子。
我們的狀態機器的代碼在下面,交互式演示已在代碼沙箱中結束。有很多,但是我們很快就會解決。明確的是,它尚不正常。
const statemachine = createmachine( { 初始:“初始”, 情境: { 開放:false, 節點:null },, 狀態:{ 最初的: { ON:{open:“打開”} },, 打開: { 在: { 渲染:{操作:“渲染”}, 調整大小:{action:“ ressize”}, 關閉:“關閉” },, 條目:“打開” },, 關閉:{ 在: { 打開:{target:“打開”,操作:[“ ressize”]}, 關閉:“關閉” },, 條目:“關閉” },, 關閉:{ 在: { 開放:“打開” },, 條目:“關閉” } } },, { 動作:{ 打開:分配(context => { 返回{...上下文,打開:true}; }), 渲染:分配(((context,evt)=> { const {node} = evt; 返回{... context,node}; }), 關閉() {}, 調整大小(上下文){}, 閉合:nistion(()=> { 返回{open:false,node:null}; })) } } );
讓我們從上到下。初始屬性控制了初始狀態,我稱之為“初始”。上下文是與我們的狀態機關聯的數據。我正在為結果列表當前是否打開,以及同一結果列表的節點對象。接下來,我們看到我們的州。每個狀態都是狀態財產中的關鍵。對於大多數州,您可以看到我們有一個屬性和入口屬性。
在配置事件上。對於每個事件,我們都可以過渡到新狀態;我們可以運行副作用,稱為動作;或兩者兼而有之。例如,當開放事件發生在初始狀態的內部時,我們將進入開放狀態。當渲染事件發生在開放狀態時,我們會執行渲染的動作。當開放事件發生在閉合狀態內時,我們將過渡到空曠狀態,並運行調整大小操作。您在大多數狀態下看到的輸入字段將在輸入狀態時自動運行的操作。儘管我們在這裡不需要它們,但也有退出操作。
我們還有更多的東西要涵蓋。讓我們看一下狀態機器的數據或上下文如何改變。當我們希望採取行動修改上下文時,我們將其包裹在分配中並從我們的行動中返回新上下文;如果我們不需要任何處理,我們可以直接通過新狀態進行分配。如果我們的操作沒有更新上下文,即,它只是用於副作用,那麼我們不會將動作功能包裹在分配中,而只是執行所需的任何副作用。
影響我們的州機器的變化
我們為我們的狀態機有一個很酷的型號,但是我們如何運行呢?我們使用解釋功能。
const statemachineservice =解釋(statemachine).start();
現在,statemachineservice是我們的運行狀態機,我們可以在該機器上調用事件以強迫我們的過渡和行動。要解僱事件,我們致電發送,傳遞事件名稱,然後選擇事件對象。例如,在結果列表首先安裝在DOM中時運行的Svelte動作中,我們有:
statemachineservice.send({type:“ rendered”,node});
這就是渲染操作獲得結果列表的節點的方式。如果您查看其餘的autocomplete.svelte文件,您將看到所有供電的狀態管理代碼替換為單線事件調度。如果輸入單擊/聚焦的處理程序,我們將運行“開放事件”。我們的resizeObserver發射了調整大小事件。等等。
讓我們暫停一下,欣賞Xstate在這裡免費給我們的東西。讓我們看一下在添加Xstate之前單擊或聚焦輸入時運行的處理程序。
函數inputEnged(evt){ 如果(關閉){ setSpringDimensions(); } open = true; Results ListVisible = true; }
之前,我們正在檢查是否要關閉,如果是這樣,則迫使我們的滑動彈簧重新計算。否則我們打開了小部件。但是,如果我們已經打開輸入時單擊輸入,會發生什麼呢?相同的代碼re-Ran。幸運的是,這並不重要。 Svelte不在乎我們是否重新設置開放,並符合他們已經持有的價值觀。但是這些擔憂隨Xstate消失了。新版本看起來像這樣:
函數inputEnged(evt){ statemachineservice.send(“ open”); }
如果我們的狀態計算機已經處於公開狀態,並且我們開了開放事件,那麼什麼也不會發生,因為沒有為該狀態配置的開放事件。當結果關閉時單擊輸入的特殊處理?這也是在狀態計算機配置中直接處理的 - 請注意,從閉合狀態運行時,開放式事件在調整大小操作上如何進行。
而且,當然,我們已經從前修復了ESC密鑰錯誤。現在,按鍵只需發射關閉事件,就是這樣。
結束
結局幾乎是反高潮的。我們需要採取以前從事的所有工作,然後將其移至我們的行動中的正確位置。 XSTATE不會消除我們編寫代碼的需求;它僅提供一個結構化的,清晰的地方。
{ 動作:{ 打開:分配({open:true}), 渲染:分配(((context,evt)=> { const {node} = evt; const dimensions = getResultSlistDimensions(node); itemSheightObserver.Observe(node); opacityspring.set(1,{hard:true}); object.Assign(slideinspring,slide_open); slideinspring.update(prev =>({... prev,width:dimensions.width}),{ 硬:是的 }); slideinspring.set(dimensions,{hard:false}); 返回{... context,node}; }), 關閉() { opacityspring.set(0); object.Assign(slideinspring,slide_close); slideinspring .update(prev =>({... prev,高度:0})) 。然後(()=> { statemachineservice.send(“關閉”); }); },, 調整大小(上下文){ opacityspring.set(1); slideinspring.set(getResultSlistDimensions(context.node)); },, 閉合:nistion(()=> { itemSheightObserver.unobserve(resultList); 返回{open:false,node:null}; })) } }
什物
我們的動畫狀態在我們的狀態機器中,但是我們如何將其清除呢?我們需要開放狀態來控制我們的結果列表渲染,儘管在此演示中未使用,但此AutoSuggest Widget的真實版本需要結果列表dom節點,例如將當前突出顯示的項目滾動到視圖中。
事實證明,我們的statemachineservice具有訂閱方法,每當發生狀態變化時就會發射。通過當前狀態機狀態調用您通過的回調,其中包括上下文對象。但是Svelte的袖子有一個特殊的技巧:其反應性語法為$:不僅可以與組件變量和Svelte商店一起使用;它還可以使用訂閱方法與任何對像一起使用。這意味著我們可以與我們的狀態機同步,這樣簡單:
$:({open,node:resuiltList} = $ statemachineservice.context);
只是常規的破壞,有一些帕倫斯(Parens)可以幫助事物正確解析。
這裡有一個快速注意,作為改進的領域。目前,我們有一些既執行副作用又更新狀態的動作。理想情況下,我們可能應該將它們分為兩個動作,一個僅用於副作用,另一個使用新狀態分配。但是,我決定讓本文盡可能簡單,以幫助減輕Xstate的引入,即使一些事情不太理想。
這是演示
分開思想
我希望這篇文章對Xstate產生了興趣。我發現它是一種非常有用,易於使用的工具來管理複雜狀態。請知道我們只刮擦了表面。我們專注於最小的FSM軟件包,但是整個Xstate庫的能力比我們在這裡涵蓋的內容(從嵌套狀態到對承諾的一流的支持)的功能要多得多,甚至具有狀態可視化工具!我敦促您檢查一下。
愉快的編碼!
以上是與Xstate協調Svelte動畫的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱門文章

熱門文章

熱門文章標籤

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)