2

我正在为测验测试显示一组问题,并为每个问题分配一个数字,以便在浏览器中显示它们时对其进行编号:

(defn questions-list
 []
  (let [counter (atom 0)]
    (fn []
      (into [:section]
           (for [question @(re-frame/subscribe [:questions])]
              [display-question (assoc question :counter (swap! counter inc))])))))

问题是,当有人在浏览器中编辑问题时(调用调度并更新“app-db”映射)组件被重新渲染,但原子“计数器”逻辑上从最后一个数字而不是从零开始. 所以我需要重置原子,但我不知道在哪里。我尝试在匿名函数中使用let,但这没有用。

4

2 回答 2

1

在这种情况下,我将完全删除该状态。我还没有测试过这段代码,但你的想法很重要。您尝试做的功能版本类似于以下内容:差但无国籍:

(let [numbers (range 0 (count questions))
      indexed (map #(assoc (nth questions %) :index %) questions)]
  [:section
   (for [question indexed]
     [display-question question])])

但这很丑陋,而且 nth 效率低下。所以让我们尝试一个更好的。事实证明 map 可以将多个集合作为它的论点。

(let [numbers (range 0 (count questions))
      indexed (map (fn [idx question] (assoc question :index idx)) questions)]
  [:section
   (for [question indexed]
     [display-question question])])

但更好的是,事实证明有一个内置函数可以做到这一点。我实际上会写:

[:section
 (doall
  (map-indexed
   (fn [idx question]
     [display-question (assoc question :index idx)])
   questions))]

注意:这些代码实际上都没有运行过,所以你可能需要在它工作之前稍微调整一下。我建议您查看ClojureDocs中的所有函数,以确保您了解它们的作用。

于 2019-12-31T05:24:13.453 回答
1

如果您counter只想成为问题的索引,则可以改用以下内容:

(defn questions-list
 []
  (let [questions @(re-frame/subscribe [:questions])
        n (count questions)]
    (fn []
      [:section
        [:ul
          (map-indexed (fn [idx question] ^{:key idx} [:li question]) questions)]])))

注意:我在这里使用[:li question],因为我认为这question是某种文本。

此外,您可以避免计算count此组件中的问题,并使用第 3 层订阅来完成:

(ns your-app.subs
  (:require
   [re-frame.core :as rf]))

;; other subscriptions...

(rf/reg-sub
 :questions-count
 (fn [_ _]
   [(rf/subscribe [:questions])])
 (fn [[questions] _]
   (count questions)))

然后在let您的组件的绑定中,您需要替换n (count questions)n @(re-frame/subscribe [:questions-count]).

于 2020-06-22T13:48:39.717 回答