目前的 ClojureScript React 绑定都是比较复杂的, 好比 Reagent, 作了很多的修改,
我打算看看直接用 cljs 裸写, 按照 React 自己的语义, 会是什么样子,
网上搜到几个版本的代码, 总之核心代码就是这样了git
(defn my-component [props context updater] (cljs.core/this-as this (js/React.Component.call this props context updater) ;; anything else you want to set-up. use goog.object/set on this this)) (gobj/extend (.. my-component -prototype) js/React.Component.prototype)
https://gist.github.com/peste...
https://gist.github.com/peste...
https://gist.github.com/thhel...github
最关键的部分就是定义一个子类继承 React.Component , 而后增长 render 方法, 参考:
https://developer.mozilla.org...this
// Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype); Rectangle.prototype.constructor = Rectangle;
最终获得的一个版本是这样,prototype
(def comp-input-area (let [Child (fn [props context updater] (this-as this (.call React/Component this props context updater) (set! (.-state this) (clj->js {:draft "initial thing"})) this))] (set! (.-prototype Child) (.create js/Object (.-prototype React/Component))) (set! (.. Child -prototype -constructor) React/Component) (set! (.. Child -prototype -render) (fn [] (this-as this (div {} (input {:value (^js .-draft (^js .-state this)), :onChange (fn [event] (.setState this (clj->js {:draft (.. event -target -value)})))}) (^js .-draft (^js .-state this)))))) Child))
注意用 this-as
这个 macro 来声明 this, 这个在 cljs 是不能随便用的,
https://stackoverflow.com/a/2...
不过这个 macro 有坑, 我用 let
的时候, this
被绑定到 window
上去了,
cljs 编译生成的代码存在一些问题, 感受 this
怎么说其实仍是很成问题的code
完整代码涉及到更多的 InterOp 用法, 不专门写了.
大概的意思就是须要转不少类型, 在上面的例子当中也看到了.
这样一来, 经过 macro 之类的手段在语法上作改进, 很难了.component
另外看到 JavaScript 有个 reify https://github.com/clojure/cl...
按说能够简化语法, 并且在 Om 代码有到看相似的用法, 无论比较复杂.
直接跟上面的例子对比, 初始化 state 的地方很差写.继承
总之很差彻底按照 React 的语义直接封装了.
当日内 Hooks 出来有带来一些改变, 不是很肯定能搞成什么样, 社区也在探索中.
https://github.com/Lokeh/hook...ip