clojurescript+;试剂问题

clojurescript+;试剂问题,clojure,clojurescript,reagent,Clojure,Clojurescript,Reagent,我正在使用clojurescript和试剂开发一个简单的web应用程序。我想创建一个简单的“tab”组件,它(对于初学者)将包含一个文本输入组件 该应用程序有两个选项卡,用户可以选择一个选项卡,我想“保留”这两个选项卡中的每个选项卡中的值 代码如下: (defn atom-input [value] [:input {:type "text" :value @value :on-change #(reset! value (-> % .-ta

我正在使用clojurescript和试剂开发一个简单的web应用程序。我想创建一个简单的“tab”组件,它(对于初学者)将包含一个文本输入组件

该应用程序有两个选项卡,用户可以选择一个选项卡,我想“保留”这两个选项卡中的每个选项卡中的值

代码如下:

(defn atom-input [value]
  [:input {:type "text"
           :value @value
           :on-change #(reset! value (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom 0)]
    (fn []
    [:div
     [:h4 (str "index: " @index)]
     [atom-input a]])))

(defn main-page []
  (let [index (atom 0)]
    [:div.container
     [:div.row
      [:button {:on-click (fn [] (reset! index 0))} "select tab 1"]
      [:button {:on-click (fn [] (reset! index 1))} "select tab 2"]]
     [:div.row
      [simple-tab index]]]))

(defn ^:export run []
  (reagent/render-component
   (fn [] [main-page])
   (.-body js/document)))
问题是,当我切换选项卡时,组件共享输入字段的值-我在这里做错了什么


非常感谢你的帮助

问题是您正在将
a(atom 0)
传递给
atom输入
控件:
[atom输入a]
。 这导致相同的atom值在选项卡之间共享

如果不想共享该值,则需要将
a
更改为映射:
a(atom{})
,并将映射和索引传递给
atom input
,例如:

(定义原子输入[值索引]
[:输入{:键入“文本”
:value(或(获取@value索引)
:更改时#(交换!值关联索引(->%.-target.-value))})
(定义简单选项卡[索引]
(let[pg指数(原子1)
a(原子{})]
(fn[]
[:div
[:h4(str“index:@index)]
[atom输入a@index]]))
IMHO是一种更好的方法,它使用游标,这样您就不需要将索引和整个映射传递给
atom input
,例如:

(定义原子输入[值]
[:输入{:键入“文本”
:value(或@value“”)
:更改时#(重置!值(->%.-target.-value))})
(定义简单选项卡[索引]
(let[pg指数(原子1)
a(原子{})]
(fn[]
[:div
[:h4(str“index:@index)]
[原子输入(试剂/光标[@index]a)]))

我认为这里有几个问题,因为您混淆了应用程序数据(状态)和显示逻辑数据(即DOM)。如果您将这两件事区分开来,即在一个原子中维护应用程序状态,在另一个原子中维护与组件显示相关的数据,那么事情可能会更干净一些

您的简单选项卡组件不需要知道关于选项卡状态的任何信息。它只需要知道应用程序状态,即通过atom输入输入/存储的值。因此,与其传递索引,不如传递希望它使用的原子。这将需要一些更高级别的逻辑来确定调用。例如,如果您有多个选项卡,则可能有如下内容

(condp = @index
  0 [simple-tab tab0-atom]
  1 [simple-tab tab1-atom]
  ...
  n [simple-tab tabn-atom])
或者您可以修改简单选项卡,以便传入的值(即索引值)用作进入应用程序状态的键-我认为光标最简单,即

(def app-state (r/atom {:tabs {0 nil 1 nil}}})

(defn simple-tab [index]
  (let [val-cur (r/cursor app-state [:tabs index])]
    [atom-input val-cur]))

您使用的是form-2组件,即返回函数的组件

详情如下:

执行此操作时,只调用返回的函数,以便您的atom输入共享同一个atom

此外,您应该在内部函数中使用相同的参数

 (defn simple-tab [index]
      (let [pg-index (atom 1)
            a (atom {})]
        (fn [index]
          [:div
           [:h4 (str "index: " @index)]
           [atom-input a @index]])))
在你的例子中,你正在传递一个原子,所以这并不重要,但是如果你忘记了这一点,你将来可能会出错

关于更广泛的体系结构,我建议您使用单个全局原子。尝试在这个原子中拥有尽可能多的状态,避免组件的局部状态,这样更容易推理

您还可以将选项卡命名为:product:users,并使用multimethod根据所选选项卡呈现正确的选项卡。这更容易阅读,也更容易在将来添加新选项卡