在昨天建立好ClojureScript專案,並且寫了一個簡單的頁面,總算一腳踏入前端網頁的世界了(狀態顯示為~逃避前端很久的後端工程師?)
在進入到接下來主題Reagent之前,
我們透過Reagent github知道Reagent是一個輕量化的ClojureScript interface to React.
只要我們熟悉cljs語法,就可以輕易地操作React。
一開始想先讓大家看看cljsInteractive programming
在前端網頁設計的威力,聞香一下:
如下圖我在第20天自己做的練習,
只要修改後存擋,
cljs就會為我們在右側的瀏覽器畫面立刻show出編譯改動過的結果,不用重loading頁面!
這種迅速反應,對使用者操作網站的體驗也會非常好。
如果覺得小妹做的純文字網頁太簡略不夠吸引人,
也可以看看這隻腦洞大開的影片Interactive programming Flappy Bird in ClojureScript,
看cljs前端大大怎麼透過操作語法讓小鳥兒自在地在空中飛舞~
目前任職公司的codebase有Angular、Vue、React這三種lagacy code都存在著,近兩年開始比較大量使用clojurescript來開發。
相信前端三大框架(Angular、Vue、React)的大名大家都不陌生,
小妹在2020年鐵人賽系列文試著用Vue做出了簡單的Kanban管理網站,但對於React目前還是一片陌生,因此首先學習的方式是想先由自己懂的概念(Vue)出發,來稍微理解一下Vue和React的共同優點。
Vue和React有以下的共同優點:
隨著專案架構越來越大,工程師開始思考如何將功能及邏輯抽象化,將模板(template)及封裝好的模組、功能可以重複使用,提供了HTML DOM的擴充性,也利於維護。
對view的修改不會直接操作 DOM,而是通過修改data。比起傳統的前端開發(如使用 jQuery)直接修改DOM,可以大大簡化程式碼。特別是當交互複雜的時候,只關心data的修改會讓邏輯變更清晰,因為DOM變成了data的映射,所有的邏輯都是針對data修改而不用碰觸DOM,讓code更利於維護。(延伸閱讀: 這位大大的React & Vue 程式說明)
當我們需要更新資料和渲染畫面時,會蠻頻繁地去新增和刪除DOM元素,造成效能問題。因此不論是Vue或React都避免直接操控DOM,而是先建立一個 Virtual DOM。當偵測到資料有更新,就會再次渲染更新的部分,但它並沒有把整個DOM換掉,並透過演算法找出與原本DOM有差異的部分,再去更新原本的DOM。
由網路上查到,React與Vue極大的差異在於React是functional programming,data immutable以及單向資料流(需要雙向的地方也可以手動藉助onChange和setState來實現)。
既然Reagent是一個簡單的React ClojureScript interface(Minimalistic React for ClojureScript)。雖然我還不太懂React,但在前面20天已經認真學過Clojure語法,應該可以努力地駕馭這個前端主題!(握拳)
在Reagent的用法上,
我們會使用 defn
這個special form
,定義一個名為 my-component
的function,
這個function會回傳html markup(標記語言) 的function,包括div和兩個p tag段落。
([] 是個會接受參數的vector,在這個例子先暫時沒用到)
(defn my-component []
[:div
[:h3 "I am a Ironman!"]
[:p.someclass
"I have a " [:strong "bold"]
[:span {:style {:color "red"}} " heart"]]])
至於為什麼可以在clojure的[]
vector裡放這麼多用clojure keyword表示 :div
, :h3
, :span
的html tag呢?原因是因為Reagent使用Hiccup這個函式庫,幫忙我們用clojure語法表達HTML。
這個Hiccup不是在說馴龍高手喔!:P
拿Day21裝錯的clojure專案試試看(原本要建的是前端cljs專案,但建了後端clojure專案),資源回收再利用一下
project.clj
加上depedency,就可以引入hiccup
套件:(defproject cljs-it-ironman "0.1.0-SNAPSHOT"
:description "My first cljs project"
:url "https://ithelp.ithome.com.tw/users/20111177/articles"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.10.1"]
[hiccup "1.0.5"]]
:repl-options {:init-ns cljs-it-ironman.core})
lein repl
: (use 'hiccup.core)
cljs-it-ironman.core=> (use 'hiccup.core)
nil
cljs-it-ironman.core=> (html [:span {:class "ting"} "Ironman"])
"<span class=\"ting\">Ironman</span>"
cljs-it-ironman.core=>
(html [:ul
(for [x (range 1 5)]
[:li x])])
"<ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>"
用clojure語言來寫html是不是很有趣呀 :)
明天我們會來玩一玩如何建立Reagent專案!