我正在建立一个基于om的表格,子章节可以被视为折叠或扩展.视图状态保存在子部分本地状态中:
(defn subsection-view [subsection owner]
(reify
om/IInitState
(init-state [this]
{:collapsed true}))
问题是每个子部分视图状态可以通过折叠 - 展开 - 全部按钮或通过为每个子部分显示的单独按钮双向实现.
为了处理expand-compress-all,以局部状态的形式保存了全局崩溃状态:
(defn form-view [data owner]
(reify
om/IInitState
(init-state [this]
{:all-collapsed true})))
显然,on-click通过更新本地状态下的折叠状态来处理两个按钮事件.
(om/update-state! owner :collapsed not)
我的问题是我应该如何知道最后更新了哪个状态才能显示正确的视图?
或者在哪里可以保存可能从组件树的不同级别中的不同触发器实现的崩溃状态的正确位置(本地状态或应用程序状态)?
如何将一串Hiccup解析为打嗝节点?
例如,
"[:b 'hello world']"进入[:b "hello world"]
Om,反应的clojurescript包装,据说非常快,因为它利用了不变性.我无法理解持久性数据结构如何在这里提供帮助.
我所理解的是应用状态是一个原子.此状态传递给返回虚拟DOM节点的函数(om组件),因此创建当前虚拟DOM与其先前状态之间差异的"补丁"比直接在实际DOM上操作要好得多.
但是持久数据结构可以在这里提供帮助吗
(def app-state (atom {:foo {:counter 0}))
(om/root click-counter app-state {:target ...})
Run Code Online (Sandbox Code Playgroud)
例如,click-counter渲染一个按钮,单击该按钮会增加计数器.所以过渡函数看起来像这样:
(dom/button #js {:onClick #(om/transact! app [:foo :counter] inc)}
(str "clicked " (-> app :foo :counter) " times"))
Run Code Online (Sandbox Code Playgroud)
我没有理解这一点:onClick执行时clojurescript创建一个新的地图(非常有效),如下所示:
{:foo {:counter 1}}
Run Code Online (Sandbox Code Playgroud)
而app-state现在指向新的地图.此时Om意识到状态已经改变,因为它只是一个等式检查的问题.
这里的问题是Om应该仍然计算整个旧虚拟DOM和新虚拟DOM之间的差异.它不知道只是计数器被改变了.
我的错误在哪里?
我有两个组件A和B.我想在页面上的这两个组件之间切换.
(defui A)
(defui B)
Run Code Online (Sandbox Code Playgroud)
一种解决方案是使用父组件C:
(defui C
(render
(let [{:keys [activeView]} props]
(if (= activeView 'A')
(renderA)
(renderB)))))
Run Code Online (Sandbox Code Playgroud)
问题是查询.C需要查询A和B,即使其中一个显示.
我需要C要么不参与查询,要么只查询A或B.
这些是真的,还是有解决方法:
app-state.我偶然发现了"examples/mixins"下的官方Om示例,其定义如下:
(def MyComponent (let [obj (om/specify-state-methods! (clj->js om/pure-methods))]
(aset obj "mixins" #js [TestMixin])
(js/React.createClass obj)))
Run Code Online (Sandbox Code Playgroud)
"#js"是什么意思?当它以这种方式使用时,我找不到符号"#"的任何Clojure文档.
是否可以编写一个不呈现任何内容的组件,例如,如果其游标数据为空?
我不能做
(defn count-or-nothing [list-cursor owner]
(reify
om/IRender
(render [_]
(if (not (empty? list-cursor))
(dom/div nil "You have some elements !")))))
Run Code Online (Sandbox Code Playgroud)
if子句返回nil,这会导致错误消息
未捕获的错误:不变违规:ReactCompositeComponent.render():必须返回有效的ReactComponent.您可能已返回null,undefined,数组或其他一些无效对象.
我通过渲染空的跨度,但听起来很笨拙.我是否必须重构我的代码并将测试"排除"在此组件之外?
我在Om中显示一个菜单,使用这样的组件和子组件:
(def app-state (atom {:location ""
:menuitems [["Pages" "/pages/"]
["Images" "/images/"]]}))
(defn menu-item-view [parent-cursor item owner]
(reify
om/IRender
(render [this]
(dom/li #js {:className (if (= (:location @app-state) (last item)) "active" "inactive")}
(dom/a #js
{:onClick (fn [_] (swap! app-state assoc :location (last @item)))}
(first item))))))
(defn menu-view [app owner]
(reify
om/IRender
(render [this]
(dom/li #js {:className "has-dropdown not-click"}
(dom/a nil "Menu")
(apply dom/ul #js {:className "dropdown"}
(om/build-all (partial menu-item-view app)
(:menuitems app)))))))
(om/root menu-view app-state
{:target (. js/document (getElementById "menu"))})
Run Code Online (Sandbox Code Playgroud)
我的问题是如何更新(@ …
首先,这个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
我还试图"手动"创建组件:
(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"))}))
Run Code Online (Sandbox Code Playgroud)
因此,这两种方法都会产生相同的警告.
React显然有一些变化.它建议以编程方式创建组件:
var React = …Run Code Online (Sandbox Code Playgroud) 在 Om Next Quick Start 中,他们使用#js和#uuid。这里的英镑符号是什么意思?
链接:https : //github.com/omcljs/om/wiki/Quick-Start-(om.next)#components-with-queries--mutations
片段:
#js:
(defui Counter
static om/IQuery
(query [this]
[:count])
Object
(render [this]
(let [{:keys [count]} (om/props this)]
(dom/div nil
(dom/span nil (str "Count: " count))
(dom/button
#js {:onClick
(fn [e] (om/transact! this '[(increment)]))}
"Click me!")))))
Run Code Online (Sandbox Code Playgroud)
#uuid:
(om/from-history reconciler
#uuid "9e7160a0-89cc-4482-aba1-7b894a1c54b4")
Run Code Online (Sandbox Code Playgroud) 假设我可以通过某个库访问纯的react.js组件:
var MyPureJavaScriptComponent = React.createClass({
render: function() {
//...
}
});
Run Code Online (Sandbox Code Playgroud)
但我希望使用om.next,其中React组件是通过defui宏构建的:
(defui MyComponent
Object
(render [this]
(div nil "Hello, world!")))
Run Code Online (Sandbox Code Playgroud)
问题:MyPureJavaScriptComponent进入的最佳方式是什么om.next?如果它可以被包装在它自己的调用中,那将是非常好的(至少在美学上),defui因此它MyPureJavaScriptComponent与其他所有om.next组件处于同一个基础上.这是否可能(并且它是最好的方式)?