0

我的“db”中有这个结构(有序映射),关键字“:questions”:

{:33 {:question "one", :id 33, :answers [{:id 22, :question_id 33, :answer "one", :correct false}
                                              {:id 4,  :question_id 33, :answer "two", :correct false}]}},
{:39 {:question "two", :id 39, :answers []}},
{:41 {:question "three", :id 41, :answers [{:id 29, :question_id 41, :answer "one", :correct false}
                                                {:id 35, :question_id 41, :answer "two", :correct true}]}} 

我可以在事件处理程序“re-frame/reg-event-db”中添加一个新问题,并添加:

(assoc-in db [:questions (:id response)] new-map-stuff)

但我不知道如何在 ":answers" 键中添加地图。此外,我担心每次添加新答案时都会渲染所有问题。

我阅读了有关“路径”拦截器(一种“更新输入”)的信息,但我找不到有关如何使用它的示例。

4

1 回答 1

1

你就像在普通的clojure中一样,使用update-in. 首先从 Clojure CheatSheet 开始:

http://jafingerhut.github.io/cheatsheet/clojuredocs/cheatsheet-tiptip-cdocs-summary.html

或 ClojureScript 版本: http ://cljs.info

查看文档update-inhttps ://clojuredocs.org/clojure.core/update-in

你需要2个组件

  1. 导航突变位点的路径
  2. 给定来自 (1) 的点的执行突变的函数。

您没有完全指定您的数据。我假设它看起来像这样:

(def db {:questions [
           {:33 {:question "one", :id 33,
                 :answers  [{:id 22, :question_id 33, :answer "one", :correct false}
                            {:id  4, :question_id 33, :answer "two", :correct false}]}},
           {:39 {:question "two", :id 39, :answers []}},
           {:41 {:question "three", :id 41,
                 :answers  [{:id 29, :question_id 41, :answer "one", :correct false}
                            {:id 35, :question_id 41, :answer "two", :correct true}]}}]})

我将制作一张新answer地图以添加:

(def new-answer {:id 42, :question_id 442, :answer "The Ultimate", :correct false})

此代码分段显示该过程。

  (let [submap       (get-in db [:questions 0 :33 :answers])
        modified     (conj submap new-answer)
        final-answer (update-in db [:questions 0 :33 :answers] conj new-answer)   ]

首先导航得到submap

submap => 
[{:id 22, :question_id 33, :answer "one", :correct false}
 {:id  4, :question_id 33, :answer "two", :correct false}]

以及添加新答案的方式:

modified => 
[{:id 22, :question_id  33, :answer "one", :correct false}
 {:id  4, :question_id  33, :answer "two", :correct false}
 {:id 42, :question_id 442, :answer "The Ultimate", :correct false}]

并将它们放在一个操作中:

final-answer => 
{:questions
 [{:33
   {:question "one",
    :id 33,
    :answers
    [{:id 22, :question_id  33, :answer "one", :correct false}
     {:id  4, :question_id  33, :answer "two", :correct false}
     {:id 42, :question_id 442, :answer "The Ultimate", :correct false}]}}
  {:39 {:question "two", :id 39, :answers []}}
  {:41
   {:question "three",
    :id 41,
    :answers
    [{:id 29, :question_id 41, :answer "one", :correct false}
     {:id 35, :question_id 41, :answer "two", :correct true}]}}]}

所有这些在 ClojureScript 中的工作方式与在 Clojure 中的工作方式相同。

不要担心使用path拦截器。我认为它使事情变得混乱而不是帮助。并且不要担心渲染速度,除非:

  1. 你让它工作和测试,并且知道它是正确的。
  2. 您已经测量了渲染速度,并且可以记录存在问题以及需要加速的量。
  3. 对于长列表,请查看key您可以添加到试剂的每个列表元素的元数据。请参阅: Reagent React Clojurescript 警告:seq 中的每个元素都应该有一个唯一的 :key

更新

请注意submapmodified出于演示目的而显示,以展示其update-in工作原理。表达式是您在代码中实际包含的update-in唯一内容。另请注意,update-in 仅使用 dband new-answer

于 2018-10-11T05:34:45.000 回答