1

背景:re-frame todomvc 示例与大多数实现一样,将所有 todos 存储为本地存储中的一个大 blob。这意味着更改 todo 的事件可以有一个用于硬编码 [:todos] 路径的路径拦截器,然后 ->localStorage 拦截器盲目地将“一切”写入 todos 键,确信“一切”只是 todos。

问题:如果我有很多相同的场景,但为了提高效率希望将每个待办事项存储在不同的键下,通过(1)分配一个 UUID,然后(2)将键创建为“TODO-”+ uuid?然后,事件向量将包含正在更改的待办事项的 uuid。

我只需要一个像“path”这样的拦截器,它可以以某种方式查看事件以确定 uuid 并将“db”缩小到那个 todo,然后有一个 writer 拦截器了解如何从上下文中获取关键信息。这样的生物存在吗?

或者也许我只是写使用 reg-event-ctx 和自定义处理一切?

还是我错过了更惯用的解决方案?

4

1 回答 1

1

我在我的一个项目中遇到了这种问题。这是我想出的解决方案:

(require '[re-frame.interceptor :refer [->interceptor get-effect get-coeffect assoc-coeffect assoc-effect]])

(defn path-by [path-key event->path]
  (->interceptor
    :id ::path-by

    :before
    (fn
      [context]
      (let [original-db  (get-coeffect context :db)
            event        (get-coeffect context :event)
            path         (or (event->path event)
                             (path-key original-db))
            original-db' (assoc original-db path-key path)]
        (assert (some? path)
                "Cannon get path neither from event->path nor from db.")
        (-> context
            (assoc ::original-db original-db')
            (assoc-coeffect :db (get-in original-db' path)))))

    :after
    (fn [context]
      (let [original-db (::original-db context)
            path        (path-key original-db)
            context'    (-> (dissoc context ::original-db)
                            (assoc-coeffect :db original-db))
            db          (get-effect context :db ::not-found)]
        (if (= db ::not-found)
          context'
          (->> (assoc-in original-db path db)
               (assoc-effect context' :db)))))))

其中大部分是从 re-frame 的原始路径拦截器中借来的。

这是使用示例:

(rf/reg-event-fx ::taks-viewed
  (path-by
    ::current-task
    (fn [[_ id]] id))
  (fn [{:keys [db]} [_ id]]
    {:db   (assoc db :loading true)
     :http {...}}))
于 2018-07-20T06:01:55.070 回答