SwiftUI之从前端视角看SwiftUI语言
生活随笔
收集整理的這篇文章主要介紹了
SwiftUI之从前端视角看SwiftUI语言
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、從 class 邁向 struct,從 class 邁向 function
- 可以將前端框架歸納為幾個要素:
-
- 元件化;
-
- 響應式機制;
-
- 狀態管理;
-
- 事件監聽;
-
- 生命周期。
- 在寫 SwiftUI 的時候總是想到 React 的發展史,最初 React 建立元件的方式是透過 JavaScript 的 class 語法,每個 React 的元件都是一個類別。
- 透過類別定義元件雖為前端元件化帶來了很大的影響,但也因為繁瑣的方法定義與 this 混淆,在 React16 hooks 出現之后,逐漸提倡使用 function component 與 hooks 的方式來建立元件。
- 省去了繼承與各種 OO 的花式設計模式,建構元件的心智負擔變得更小了。從 SwiftUI 當中,也可以看到類似的演進,原本 ViewController 龐大的 class 以及職責,要負責 view 與 model 的互動,掌管生命周期,轉為更輕量的 struct,讓開發者可以更專注在 UI 互動上,減輕認知負擔。
二、元件狀態管理
- React 16 采取了 hooks 來做元件的邏輯復用與狀態管理,例如 useState:
- 在 SwiftUI 當中,可以透過修飾符 @State 讓 View 也具有類似效果。兩者都具備響應式機制,當狀態變數發生改變時,React/Vue 會偵測改變并反映到畫面當中。雖然不知道 SwiftUI 背后的實作,但背后應該也有類似 diff 機制的東西來達到響應式機制與最小更新的效果。
- 然而 SwiftUI 的狀態管理與 React hooks 仍有差異,在 React 當中,可以將 hook 拆成獨立的函數,并且在不同的元件當中使用,例如:
- 在 React 當中,可以將 toggle 的邏輯拆出,并在不同元件之間使用,由于 useToggle 是一個純函數,因此內部的狀態也不會互相影響。
- 然而在 SwiftUI 當中 @State 只能作用在 struct 的 private var 當中,不能進一步拆出。如果想要將重復的邏輯抽出,需要另外使用 @Observable 與 @StateObject 這樣的修飾符,另外建立一個類別來處理。
- 在這個例子當中把 toggle 的邏輯拆成一個 class 似乎有點小題大作了,不過仔細想想像 React 提供的 hook 功能,讓輕量的邏輯共用就算單獨拆成 hook 也不會覺得過于冗長,若要封裝更復雜的邏輯也可以再拆分成更多 hooks,從這點來看 hook 的確是一個相當優秀的機制。后來看到了 SwiftUI-Hooks,不知道實際使用的效果如何。
- 以 React 來說,在還沒有出現 hooks 之前,主要有三個方式來實作邏輯共用:
-
- HOC(Higher Order Component):將共同邏輯包裝成函數后返回全新的 class,避免直接修改元件內部的實作,例如早期 react-redux 中的 connect;
-
- render props:將實際渲染的元件當作屬性(props)傳入,并提供必要的參數供實作端使用;
-
- children function:children 只傳入必要的參數,由實作端自行決定要渲染的元件。
三、Redux 與 TCA
- 受到 Redux 的影響,在 Swift 當中也有部分開發者使用了采用了類似手法,甚至也有相對應的實作 ReSwift 的說明文。從說明文可以看到主要原因,傳統的 ViewController 職責曖昧,容易變得肥大導致難以維護,透過 Reducer、Action、Store 訂閱來確保單向資料流,所有的操作都是向 store dispatch 一個 action,而資料的改動(mutation)則在 reducer 處理。
- 而最近的趨勢似乎從 Redux 演變成了 TCA(The Composable Architecture),跟 Redux 的中心思想類似,更容易與 SwiftUI 整合,比較不一樣的地方在于以往涉及 side effect 的操作在 Redux 當中會統一由 middleware 處理,而在 TCA 的架構中 reducer 可以回傳一個 Effect,代表接收 action 時所要執行的 IO 操作或是 API 呼叫。
- 既然采用了類似 redux 的手法,不知道 SwiftUI 是否會遇到與前端開發類似的問題,例如 immutability 確保更新可以被感知;透過優化 subscribe 機制確保 store 更新時只有對應的元件會更新;reducer 與 action 帶來的 boilerplate 問題。
- 雖然 Redux 在前端仍然具有一定地位,也仍然有許多公司正在導入,然而在前端也越來越多棄用 Redux 的聲音,主要因為 redux 對 pure function 的追求以及 reducer、action 的重復性極高,在應用沒有到一定復雜程度之前很難看出帶來的好處,甚至連 Redux 作者本人也開始棄坑 redux 了 4。與此同時,react-redux 仍然有在持續更新,也推出了 redux-toolkit 來試圖解決導入 redux 時常見的問題。
- 取而代之的是更加輕量的狀態管理機制,在前端也衍生出了幾個流派:
-
- GraphQL → 使用 apollo 或是 relay;
-
- react-query;
-
- react-swr;
-
- recoil;
-
- jotai。
四、全域狀態管理
- 在全域狀態管理上,SwiftUI 也有內建機制叫做 @EnvrionmentObject,其運作機制很像 React 的 context,讓元件可以跨階層存取變數,當 context 改變時也會更新元件:
- 從上面這個范例可以發現,不需要另外傳入 user 給 UserInfo,透過 @EnvrionmentObject 可以拿到當前的 context。轉換成 React 的話會像這樣:
- React 的 context 可讓元件跨階層存取變數,當 context 改變時也會更新元件。雖然有效避免了 prop drilling 的問題,然而 context 的存在會讓測試比較麻煩一些,因為使用 context 時代表了某種程度的耦合。
五、響應機制
- 在 React 當中,狀態或是 props 有變動時都會觸發元件更新,透過框架實作的 diff 機制比較后反映到畫面上。在 SwfitUI 中也可以看到類似的機制:
- 一個典型的 SwiftUI 元件是一個 struct,透過定義 body 變數來決定 UI。跟 React 相同,它們都只是對 UI 的抽象描述,透過比對資料結構計算最小差異后,再更新到畫面上。
- @State 修飾符可用來定義元件內部狀態,當狀態改變時會更新并反映到畫面中。在 SwiftUI 當中,屬性(MyView 當中的 name)可以由外部傳入,跟 React 當中的屬性(props)類似。
- 用 React 改寫這個元件的話會像這樣:
- 在撰寫 SwiftUI 時會發現這跟以往用 UIKit、UIController 的開發方式不太一樣。
六、列表
- SwiftUI 與 React 當中都可以渲染列表,而撰寫的方式也有雷同之處。在 SwiftUI 當中可以這樣寫:
- 轉成 React 大概會像這樣子:
- 在渲染列表時為了確保效能,減少不必要的比對,React 會要求開發者提供 key,而在 SwiftUI 當中也有類似的機制,開發者必須使用叫做 Identifiable[11] 的 protocol,或是顯式地傳入 id。
七、Binding
- 除了將變數綁定到畫面之外,也可以將互動綁定到變數之中。例如在 SwiftUI 當中我們可以這樣寫:
- 在這個范例當中,就算不監聽輸入事件,使用 $text 也可以直接改變 text 變數,當使用 @State 時會加入 property wrapper,會自動加入一個前綴 $,型別為 Binding。
- React 并沒有雙向綁定機制,必須要顯式監聽輸入事件確保單向資料流。不過像 Vue、Svelte 都有雙向綁定機制,節省開發者手動監聽事件的成本。
八、Combine 的出現
- 雖然我對 Combine 還不夠熟悉,但從官方文件與影片看起來,很像RxJS 的 Swift 特化版,提供的 API 與操作符大幅度地簡化了復雜資料流。這讓我想起了以前研究 RxJS 與 redux-observable 各種花式操作的時光,真令人懷念。
九、總結
- 前文提到那么多,然而網頁與手機開發仍然有相當大的差異,其中對我來說最顯著的一點是靜態編譯與動態執行。動態執行可以說是網頁最大的特色之一。
- 只要有瀏覽器,JavaScript、HTML、CSS,不管在任何裝置上都可以成功執行,網頁不需要事先下載 1xMB ~ 幾百 MB 的內容,可以動態執行腳本,根據瀏覽的頁面動態載入內容。
- 由于不需要事先編譯,任何人都可以看到網頁的內容與執行腳本,加上 HTML 可以 streaming 的特性,可以一邊渲染一邊讀取內容。難能可貴的一點是,網頁是去中心化的,只要有伺服器、ip 位址與網域,任何人都可以存取網站內容;而 App 如果要上架必須事先通過審查。
- 不過兩者的生態圈與開發手法有很大的不同,仍然建議參考一下彼此的發展,就算平時不會碰也沒關系,從不同的角度看往往可以發現不同的事情,也可以培養對技術的敏銳度。
總結
以上是生活随笔為你收集整理的SwiftUI之从前端视角看SwiftUI语言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据结构与算法】之深入解析“格雷编码”
- 下一篇: Swift之深入解析类和结构体的本质