如何在 Om Clojurescript 中创建 Material UI 组件?
How to create Material UI component in Om Clojurescript?
首先,这个 https://github.com/taylorSando/om-material-ui 不适用于最新的 React/Material UI。
我认为主要原因是控制台中的警告:
Warning: Something is calling a React component directly. Use a factory or JSX instead. See: https://fb.me/react-legacyfactory
我也试过创建组件 "manually":
(ns om-test.core
(:require [om.core :as om :include-macros true]
[om-tools.dom :as dom :include-macros true]
[om-tools.core :refer-macros [defcomponent]]
[om-material-ui.core :as mui :include-macros true]))
(enable-console-print!)
(defonce app-state (atom {:text "Hello Chestnut!"}))
(defn main []
(om/root
(fn [app owner]
(reify
om/IRender
(render [_]
(dom/div (dom/element js/MaterialUI.Paper {} "Hello")
(mui/paper {} "Hello"))
)))
app-state
{:target (. js/document (getElementById "app"))}))
因此,这两种方法都会产生上述相同的警告。
React 显然发生了一些变化。它建议以编程方式创建组件:
var React = require('react');
var MyComponent = React.createFactory(require('MyComponent'));
function render() {
return MyComponent({ foo: 'bar' });
}
那么我如何在 Om 渲染函数中创建 Material UI 组件,或者可能更好 我通常如何在 Om 渲染函数中创建 React 组件?
MaterialUI我的意思是https://github.com/callemall/material-ui
我的依赖
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-3058" :scope "provided"]
[ring "1.3.2"]
[ring/ring-defaults "0.1.4"]
[compojure "1.3.2"]
[enlive "1.1.6"]
[org.omcljs/om "0.9.0"]
[environ "1.0.0"]
[http-kit "2.1.19"]
[prismatic/om-tools "0.3.11"]
[om-material-ui "0.1.1" :exclusions [org.clojure/clojurescript
org.clojure/clojure]]]
我没有使用 Material UI 但 React Widgets. Here is the wrapper 我需要为 om 编写:
(defn dropdown-list
[data owner {:keys [val-key menu-key id-key label-key props]}]
(reify
om/IRender
(render [_]
(let [menu (-get data menu-key)]
(js/React.createElement js/ReactWidgets.DropdownList
(-> {:defaultValue (-> (find-by-key menu id-key (-get data val-key))
(-get label-key))
:data (mapv #(-get % label-key) menu)
:onChange (fn [new-val]
(let [new-id (-> (find-by-key menu label- key new-val)
(-get id-key))]
(om/update! data val-key new-id)))}
(merge props)
clj->js))))))
因此,一般来说,您需要获取 React class (js/ReactWidgets.DropdownList
) 并在 render
上传递道具时调用 js/Readt.createElement
。
好吧,我终于明白了。
- 构建 Material UI 的最新版本:https://github.com/taylorSando/om-material-ui/tree/master/build-mui。注意:不需要在当前版本(0.10.4)
中构建CSS
- 将内置
material.js
包含到您的 HTML 文件中。同样,无需包含 CSS.
- 避免加载 React 两次 https://github.com/taylorSando/om-material-ui#avoid-loading-react-twice
现在 Om 的代码:
(ns material-ui-test.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]))
(enable-console-print!)
(defonce app-state (atom {:text "Hello Chestnut!"}))
(def ^:dynamic *mui-theme*
(.getCurrentTheme (js/MaterialUI.Styles.ThemeManager.)))
(defn main []
(om/root
(fn [app owner]
(reify
om/IRender
(render [_]
(let [ctor (js/React.createFactory
(js/React.createClass
#js
{:getDisplayName (fn [] "muiroot-context")
:childContextTypes #js {:muiTheme js/React.PropTypes.object}
:getChildContext (fn [] #js {:muiTheme *mui-theme*})
:render (fn []
(dom/div nil
(dom/h1 nil (:text app))
(js/React.createElement js/MaterialUI.Slider)))}))]
(ctor. nil)))))
app-state
{:target (. js/document (getElementById "app"))}))
如果你只使用 (js/React.createElement js/MaterialUI.Slider)
而没有使用 :getChildContext
等,它会抛出错误:
Uncaught TypeError: Cannot read property 'component' of undefined
这是因为当前 MaterialUI 的工作原理。在此处阅读 "Usage" 部分:http://material-ui.com/#/customization/themes
Reagent 的代码更优雅一些。但是我在这里使用了命名空间
[material-ui.core :as ui :include-macros true]
从这个示例项目中复制粘贴:https://github.com/tuhlmann/reagent-material
(def ^:dynamic *mui-theme*
(.getCurrentTheme (js/MaterialUI.Styles.ThemeManager.)))
(defn main-panel []
(let [active-panel (rf/subscribe [:active-panel])]
(r/create-class
{:display-name "Main Panel"
:child-context-types
#js {:muiTheme js/React.PropTypes.object}
:get-child-context
(fn [this]
#js {:muiTheme *mui-theme*})
:reagent-render
(fn []
[ui/Slider {:name "slide1"}])})))
编辑: 我发布了库,大大简化了整个过程。
图书馆:https://github.com/madvas/cljs-react-material-ui
示例应用程序:https://github.com/madvas/cljs-react-material-ui-example
首先,这个 https://github.com/taylorSando/om-material-ui 不适用于最新的 React/Material UI。 我认为主要原因是控制台中的警告:
Warning: Something is calling a React component directly. Use a factory or JSX instead. See: https://fb.me/react-legacyfactory
我也试过创建组件 "manually":
(ns om-test.core
(:require [om.core :as om :include-macros true]
[om-tools.dom :as dom :include-macros true]
[om-tools.core :refer-macros [defcomponent]]
[om-material-ui.core :as mui :include-macros true]))
(enable-console-print!)
(defonce app-state (atom {:text "Hello Chestnut!"}))
(defn main []
(om/root
(fn [app owner]
(reify
om/IRender
(render [_]
(dom/div (dom/element js/MaterialUI.Paper {} "Hello")
(mui/paper {} "Hello"))
)))
app-state
{:target (. js/document (getElementById "app"))}))
因此,这两种方法都会产生上述相同的警告。
React 显然发生了一些变化。它建议以编程方式创建组件:
var React = require('react');
var MyComponent = React.createFactory(require('MyComponent'));
function render() {
return MyComponent({ foo: 'bar' });
}
那么我如何在 Om 渲染函数中创建 Material UI 组件,或者可能更好 我通常如何在 Om 渲染函数中创建 React 组件?
MaterialUI我的意思是https://github.com/callemall/material-ui
我的依赖
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-3058" :scope "provided"]
[ring "1.3.2"]
[ring/ring-defaults "0.1.4"]
[compojure "1.3.2"]
[enlive "1.1.6"]
[org.omcljs/om "0.9.0"]
[environ "1.0.0"]
[http-kit "2.1.19"]
[prismatic/om-tools "0.3.11"]
[om-material-ui "0.1.1" :exclusions [org.clojure/clojurescript
org.clojure/clojure]]]
我没有使用 Material UI 但 React Widgets. Here is the wrapper 我需要为 om 编写:
(defn dropdown-list
[data owner {:keys [val-key menu-key id-key label-key props]}]
(reify
om/IRender
(render [_]
(let [menu (-get data menu-key)]
(js/React.createElement js/ReactWidgets.DropdownList
(-> {:defaultValue (-> (find-by-key menu id-key (-get data val-key))
(-get label-key))
:data (mapv #(-get % label-key) menu)
:onChange (fn [new-val]
(let [new-id (-> (find-by-key menu label- key new-val)
(-get id-key))]
(om/update! data val-key new-id)))}
(merge props)
clj->js))))))
因此,一般来说,您需要获取 React class (js/ReactWidgets.DropdownList
) 并在 render
上传递道具时调用 js/Readt.createElement
。
好吧,我终于明白了。
- 构建 Material UI 的最新版本:https://github.com/taylorSando/om-material-ui/tree/master/build-mui。注意:不需要在当前版本(0.10.4) 中构建CSS
- 将内置
material.js
包含到您的 HTML 文件中。同样,无需包含 CSS. - 避免加载 React 两次 https://github.com/taylorSando/om-material-ui#avoid-loading-react-twice
现在 Om 的代码:
(ns material-ui-test.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]))
(enable-console-print!)
(defonce app-state (atom {:text "Hello Chestnut!"}))
(def ^:dynamic *mui-theme*
(.getCurrentTheme (js/MaterialUI.Styles.ThemeManager.)))
(defn main []
(om/root
(fn [app owner]
(reify
om/IRender
(render [_]
(let [ctor (js/React.createFactory
(js/React.createClass
#js
{:getDisplayName (fn [] "muiroot-context")
:childContextTypes #js {:muiTheme js/React.PropTypes.object}
:getChildContext (fn [] #js {:muiTheme *mui-theme*})
:render (fn []
(dom/div nil
(dom/h1 nil (:text app))
(js/React.createElement js/MaterialUI.Slider)))}))]
(ctor. nil)))))
app-state
{:target (. js/document (getElementById "app"))}))
如果你只使用 (js/React.createElement js/MaterialUI.Slider)
而没有使用 :getChildContext
等,它会抛出错误:
Uncaught TypeError: Cannot read property 'component' of undefined
这是因为当前 MaterialUI 的工作原理。在此处阅读 "Usage" 部分:http://material-ui.com/#/customization/themes
Reagent 的代码更优雅一些。但是我在这里使用了命名空间
[material-ui.core :as ui :include-macros true]
从这个示例项目中复制粘贴:https://github.com/tuhlmann/reagent-material
(def ^:dynamic *mui-theme*
(.getCurrentTheme (js/MaterialUI.Styles.ThemeManager.)))
(defn main-panel []
(let [active-panel (rf/subscribe [:active-panel])]
(r/create-class
{:display-name "Main Panel"
:child-context-types
#js {:muiTheme js/React.PropTypes.object}
:get-child-context
(fn [this]
#js {:muiTheme *mui-theme*})
:reagent-render
(fn []
[ui/Slider {:name "slide1"}])})))
编辑: 我发布了库,大大简化了整个过程。
图书馆:https://github.com/madvas/cljs-react-material-ui
示例应用程序:https://github.com/madvas/cljs-react-material-ui-example