Skip to content

Instantly share code, notes, and snippets.

@jiyinyiyong jiyinyiyong/ Secret

Created Dec 4, 2016
What would you like to do?
Talk on React and ClojureScript

从 React 到 ClojureScript


  • 题叶,
  • jiyinyiyong
  • ChenYong
  • 饿了么, 前端
  • FP, GUI & Writing


  • 介绍 ClojureScript
  • React 某些缺陷并不是必然
  • ClojureScript 一些例子

什么是 ClojureScript


(def a 1)
(def add-1 [x] (+ x 1))
(println (add-1 a))


  • Lisp 方言
  • 不可变数据
  • Rich Hickey


  • Clojure -> JVM
  • ClojureScript -> Browsers
  • ClojureScript -> Node.js , JavaScriptCore

Learn Clojure in Y minutes

A Demo.

brew install lumo

React 有哪些特点

Pure Functional

  • 渲染 Virtual DOM 的纯函数
  • Store Updater 使用纯函数
  • 代码大量复用, 无副作用

Immutable Data Structure

  • 性能优化手段, 通过引用查找未改变的数据
  • 数据流的单向性, 可靠性


  • 组件成为代码复用的单元
  • 组件也是性能优化过程中的单元

React 有哪些问题


  • JSX, statement vs. expression
  • this 需要额外处理
  • immutable-js 和原生数据类型混用
  • this.state 不够灵活, this.setState 过程式编程


  • Babel 更新频繁, 200+ 个版本, 配置繁杂
  • Redux 生态, unknown
  • 热替换手法复杂
  • 强行把组件封装成元素的结构, props, children

Better with ClojureScript

问题: JSX


(if (> x 10) "big" "small")

非常时候构造 DSL.

Clojure 语言非常稳定, 不接受社区的 PR. 只能通过类库进行扩展.

问题: this

几乎没有 this. 完全通过函数来构造, 而不是 class.

问题: "数据混杂"

基于不可变数居, 严格限制可变数据的使用

(def a {:a 1, :b 2})
(assoc a :c 3)

(def b [1 2])
(conj b 3)

(def c '(6 5 4))
(cons 7 c)

(def d #{:a :b :c})
(conj d :d)

问题: this.state

atom 重新抽象 state:

(def click-count (r/atom 0))

(defn counting-component []
   "The atom " [:code "click-count"] " has value: "
   @click-count ". "
   [:input {:type "button" :value "Click me!"
            :on-click #(swap! click-count inc)}]])

问题: Redux (替代方案)

Atom, 内置数据类型, Observable, 一个引用:

(def state-x (atom 0))
(add-watch state-x :logger (fn []
                               (println "Changed!")))
(reset! state-x 1) ; prints "Changed!"

(println @state-x) ; dereference to get value


Reagent: 挂载组件

(defn simple-component []
   [:p "I am a component!"]
    "I have " [:strong "bold"]
    [:span {:style {:color "red"}} " and red "] "text."]])

(defn render-simple []
  (r/render-component [simple-component]
                      (.-body js/document)))

Reagent: 处理 component state

(defn atom-input [value]
  [:input {:type "text"
           :value @value
           :on-change #(reset! value (-> % .-target .-value))}])

(defn shared-state []
  (let [val (r/atom "foo")] ; <---- atom
    (fn []
       [:p "The value is now: " @val]
       [:p "Change it here: " [atom-input val]]])))

Reagent: 组件嵌套

(defn hello-component [name]
  [:p "Hello, " name "!"])

(defn say-hello []
  [hello-component "world"])

Respo: a font-end MVC library(experimental)


  • 首屏加载时使用 Patching, 优化动画(渐进渲染)
  • 将 Virtual DOM 作为数据, 插入/改写
  • Virtual DOM for Canvas, 用框架来描述动画状态
  • Virtual tree for data, 服务端做数据的 diff, 带缓存优化(递进渲染)
  • core.async 来增强时间相关逻辑

Respo demo

Some demos...


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.