我想使用ClojureScript中的Google Closure UI组件和Rum / React库。
我从goog.ui.DatePicker开始,但仍无法正确包装。下面的代码在组件挂载上呈现DatePicker一次,在正确的位置,事件监听器工作,一切都很好,除了它需要在dom节点上静态设置id(" here")才能工作一次性攻击是可以接受的,但是当我需要将组件包裹起来并在同一页面/应用程序上多次使用时,这是不可接受的。
(ns redux.components
(:require [rum.core :as r]
[cljs-time.core :as time]
[cljs-time.format :as tf]
[goog.dom :as dom]
[goog.ui.DatePicker :as goog-picker]
[goog.events :as goog-events]]))
(r/defcs +published-at < { :did-mount (fn [state]
(let [target-node (:r/ref state "here")
dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println "new date is: " (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp (goog.dom/getElement "here")))
state) }
[]
[:div#here])
(r/defc app
[]
[:div
[:h1 "title"
(+published-at)]])
反应documentation suggests,为了与第三方DOM库集成,可能需要引用。朗姆酒documentation describes怎么办对朗姆酒做出反应。但问题是React doc声明字符串引用是遗留的,并且可能在将来的版本中删除,而Rum文档不包括基于回调的引用。我试着猜测如何将两个框架与字符串引用以及回调引用结合起来,但似乎没有一个工作:
(r/defcs +published-at < { :did-mount (fn [state]
(let [target-node (:r/ref state "here")
dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp target-node))
state) }
[]
[:div
[:div { :ref "here" } ]])
失败并出现错误,甚至没有显示DatePicker:
Uncaught TypeError: opt_parentElement.insertBefore is not a function
at goog.ui.DatePicker.goog.ui.Component.render_ (component.js:705)
at goog.ui.DatePicker.goog.ui.Component.render (component.js:659)
at Function.<anonymous> (components.cljs?rel=1493075625598:123)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$3 (core.cljs:3694)
at cljs$core$apply (core.cljs:3676)
at util.cljc?rel=1492772300984:17
at core.cljs:2314
at Function.cljs.core.seq_reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2314)
at cljs.core.LazySeq.cljs$core$IReduce$_reduce$arity$3 (core.cljs:3287)
at Function.cljs.core.reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2358)
(r/defcs +published-at < { :did-mount (fn [state]
(let [dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp (::put-date-here state)))
state) }
[state]
[:div
[:div { :ref #(assoc state ::put-date-here %) }]])
这会在页面的末尾呈现功能性的DatePicker,但不在组件之外。
答案 0 :(得分:0)
此处不需要:did-mount
,只需在回调中将其渲染。这对我来说很好:
(defn show-datepicker
[d]
(let [dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE)
#(js/console.info
(.. % -target getDate)))
(.render dp d)))
[:div {:ref show-datepicker}]
如果您需要拆除日期选择器,那么只需检查(nil? d)
中的show-datepicker
即可。当组件卸载时,React将传递nil。
PS:除非你真的喜欢大js输出文件,否则我不会使用cljs-time
。