Skip to content

Instantly share code, notes, and snippets.

@jiyinyiyong jiyinyiyong/react-to-cljs.md Secret
Created Dec 4, 2016

Embed
What would you like to do?
Talk on React and ClojureScript

从 React 到 ClojureScript


关于我

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

目标

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

什么是 ClojureScript


ClojureScript

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

ClojureScript

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

运行环境

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

Learn Clojure in Y minutes

http://learnxinyminutes.com/docs/clojure

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 []
  [:div
   "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

http://reagent-project.github.io/


Reagent: 挂载组件

(defn simple-component []
  [:div
   [:p "I am a component!"]
   [:p.someclass
    "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 []
      [:div
       [: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...


Thx

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.