type Model = { x : int }
type Msg = Increment | Decrement
let init () =
{ x = 0 }, Cmd.ofMsg Increment
let update msg model =
match msg with
| Increment -> { model with x = model.x + 1 }, Cmd.none
| Decrement -> { model with x = model.x - 1 }, Cmd.none
let view model dispatch =
div []
[
div [] [str (string model.x)]
button [OnClick (fun e -> dispatch Increment)] [str "+" ]
button [OnClick (fun e -> dispatch Decrement)] [str "-" ]
]
Program.mkProgram init update view
|> Program.run
複製代碼
整個程序真的是太簡潔易懂了,可能會有一些語法須要習慣,好比type Msg = Increment | Decrement
中的|
至關於就是或
,而match msg with
相似switch case
,可是功能強大不少。view裏面的div [放HTML標籤屬性] [放子元素]
。整個程序幾乎每一行都是在寫本身的業務,冗餘的內容不多,真是太優雅了。忍不住要把本身的第一篇文章要用來寫這個。html
函數式編程的語言不少,能用作前端的彷佛也很多,包括fsharp, scala等。因爲本人主要混在.net平臺,因此對fsharp瞭解比較多。用fsharp寫前端主要是靠Fable把fsharp編譯成js(FSharp |> Fable |> Bable |> Webpack |> js)。前端
Elmish 是一個設計思想,應該是和mvvm平級,理念相似redux,可是時間是應該更早一點。具體能夠參看https://elmish.github.io/elmish/。因此debug的時候也能夠用redux的chrome插件查看狀態等。vue
Fable只是一個編譯器,除了view其餘的都是單純的邏輯,而view裏面的東西能夠是不少前端的框架技術好比react(上例用的就是), react native, 也能夠是原生的html,或者vue等,可是Fable社區裏面最流行的仍是react。因此react生態裏的全部控件均可以使用,可是爲了有fsharp的類型提醒須要寫一些類型聲明,這個相似於typescript的.d.ts裏寫的東西;因此社區裏也有人寫了一些工具把.d.ts的內容直接翻譯成fsharp可以使用的類型(目前尚未試過)。固然也能夠自行綁定原生js,好比須要引入npm的庫的時候就要作這種事情。具體參見http://fable.io/docs/interacting.htmlreact
代碼託管在https://github.com/albertwoo/Tetrisandroid
項目初始化是用社區裏一個模板生成的[https://github.com/SAFE-Stack],包括的內容不少,如自動化編譯,打包,熱更新,測試等,代碼也有不少如Client, Server, Test等,目前不須要Server,因此目前的主要代碼都在src/Client下面。git
TetrisDomain.fs
定義了俄羅斯方塊的基本類型以及一些操做好比操做Block,查看是否相撞,或者清除知足條件的行等。Square是指最小的馬賽克方塊,Block是指下落的物體:github
type Square = { Location: int * int; Color: int * int * int * float }
type BlockType = T | L | J | I | O | Z | RZ | X
type Block = { Type: BlockType; Squares: Square list }
type Action = Rotate | Left | Right | Down
...
複製代碼
Tetris.fs
至關於寫了一個組件,包括了狀態,更新狀態,以及界面的一些東西:chrome
type Model = {
SquareSize: int
Boundry: int * int
AllSquares: Square list
PreviewBlock: Block option
MovingBlock: Block option
PrectionBlock: Block option
IsOver: bool
Score: int
DefaultSpeed: int
Speed: int
SpeedCount: int }
type Msg = | Action of Action | ReachBottom | ReachLeft | ReachRight
複製代碼
App.fs
是整個程序的入口,會把Tetris定義的東西整合進來,也包含了一些界面的佈局,開始,暫停,從新開始等操做。typescript
type Model = {
Tetris: Tetris.Model
TimeCost: int
TouchStartPoint: (float * float) option
TouchMovingPoint: (float * float) option
TouchTime: DateTime option
IsPaused: bool
IsRestarting: bool
HideDetail: bool }
type Msg =
| TetrisMsg of Tetris.Msg
| BeginRestart | CancelRestart | Restart
| Tick
| TouchStart of float * float | TouchMove of float * float | TouchEnd of float * float
| Pause | Continue
| HideDetail
複製代碼
整個程序的組件的拆分沒有作得很好,邏輯不是很清晰,做爲學習勉強接受吧。 整個效果以下,也能夠在線體驗,觸控最佳,鍵盤勉強可用:npm
函數式編程彷佛離成爲主流還有很長的路,在現代的服務器方面的應用應該比較多,畢竟微服務的流行致使框架和語言的選擇變得更靈活。可是在前端方面的應用不多,android, xamarin等本地應用的開發都大量使用mvvm的設計模式。之前我開發過wpf,都是基於mvvm,如今開發angular幾乎天然上手,設計思想一模一樣。React卻是特立獨行,包括其中流行的redux狀態管理也頗有獨到之處。vue給個人感受就顯得抱負很大什麼都想作,可是我的淺嘗後最後仍是選擇了angular,畢竟有typescript的完美融合。
由於項目啓動後已經使用了angular,可是也想利用redux的一些先進思想,後來嘗試ngrx,可是發現須要寫太多冗餘的代碼,並且分散在不少不一樣的文件,加之js的語言特性,寫actions, reducers, selectors的時候簡直婆婆媽媽,讓我失去耐心,冗餘代碼幾乎遇上業務邏輯代碼,因此最後仍是放棄。不過angular自己的設計已經在個人項目夠用了,除了有點囉嗦。
面向對象還大行其道,而且對各類問題都有着成熟的解決方案,上面所言都是在下實踐所得的經驗,沒有嚴格的理論支持,純屬我的妄言,聽聽就是,也可嗤之以鼻。