【问题标题】:How to correctly wrap Google Closure UI Component as Rum Component如何正确地将 Google Closure UI 组件包装为 Rum 组件
【发布时间】:2017-04-24 23:42:31
【问题描述】:

我想将 ClojureScript 中的 Google Closure UI 组件与 Rum/React 库一起使用。

我从 goog.ui.DatePicker 开始,但仍然无法正确包装它。下面的代码在组件安装时在正确的位置渲染一次 DatePicker,事件侦听器工作并且一切都很好,除了它需要在 dom 节点上静态设置的 id(“here”)才能工作,这一次是可以接受的hack,但当我需要包装组件并在同一页面/应用程序上多次使用时不需要。

(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)]])

我进一步的失败研究

React documentation suggests 与第三方 DOM 库集成可能需要引用。朗姆酒documentation describes 如何对朗姆酒的参考文献做出反应。但问题是 React 文档指出字符串引用是遗留的,可能会在未来的版本中被删除,而 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,但在组件之外。

【问题讨论】:

    标签: reactjs clojurescript google-closure-library


    【解决方案1】:

    这里不需要: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}]
    

    如果您需要拆除日期选择器,则只需在您的 show-datepicker 中检查 (nil? d)。当组件卸载时,React 将传递 nil。

    PS:除非你真的喜欢大的 js 输出文件,否则我不会使用 cljs-time

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2021-01-22
      • 2017-03-11
      相关资源
      最近更新 更多