【问题标题】:How to create a custom "getter" query in cljs re-frame?如何在 cljs re-frame 中创建自定义“getter”查询?
【发布时间】:2020-01-03 05:33:21
【问题描述】:

我正在编写一个重新构建应用程序来模拟棋盘游戏,其中我有一个包含一组单元格的棋盘结构,例如:

{... :board-cells [{:name "cell-1" :material #object} {:name "cell-2" :material #object} ...]}

虽然 re-frame 支持使用像 (db :board-cells) 这样漂亮的关键字语法获取“自然”子结构,但我已经厌倦了每次想要获取材料时都必须编写整个“向下钻取”查询:(get (nth (db :board-cells) index) :material)。这也有将我的数据库的物理布局与我的应用程序逻辑紧密耦合的缺点。如果我决定改变我的数据库结构怎么办?然后我必须更新十个不同的点,而不仅仅是一个。

是否有一种重新构建官方方法来创建“虚拟查询”,这样我就可以获得类似(db :get-nth-mat n) 的材料,其中 n 是board-cells 数组中的单元格编号?我认为db.cljs 和reg-sub 是我可以做到这一点的地方,但它似乎不起作用。是的,我可以创建自己的 getter:

(defn get-material [db index]
  (get (nth (db :board-cells) index) :material))

并称它为(println "mat-4=" (cell/get-material db 4)),但这不如(db :get-nth-mat n) 方便或好听

非常感谢。

【问题讨论】:

    标签: clojurescript re-frame


    【解决方案1】:

    db 只是一张地图,与此“功能”无关 重新框架,但每张地图都是一个功能,关键字也是如此。所以当你 做(map something) 或(:keyword something) 你实际上在做 (get map something) 和 (get something :keyword)。

    所以除了访问/迭代你的 数据不同(例如doseq,for,map,...) - 假设你是 即将逐个单元格地渲染网格;这样你就摆脱了 完全基于索引的访问。

    否则我会使用像你这样的专用功能,但宁愿命名 它material-by-idx(命名函数get 和 set 类似于 OO 中的访问器(但也有类似的地方,例如 设置状态修改))。

    拥有正确命名的、理想的纯函数,做一件事 正确地是函数式和 Lisp 中的重要组成部分 编程。通常不得不多输入一点的缺点可能是 由更高级别的编程范例(如线程或部分)减轻 应用程序或作为最后的手段,宏。

    您可以使用get-in 来整理一下:

    (defn material-by-idx [db idx]
      (get-in db [:board-cells idx :material]))
    

    例如你现在可以在你的循环中使用这样的东西,如果你看到 价值在于:

    (let [mat-at (partial material-by-idx db)]
      (mat-at 5))
    

    顺便说一句:你想要的版本 (db :get-nth-mat n) 实际上 工作(但不是你想要的)。它变成(get db :get-nth-mat n)(3 个参数get),如果没有密钥,它会返回n :get-nth-mat 在db。

    【讨论】:

      猜你喜欢
      • 2018-08-15
      • 2014-09-06
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多