如何用Specter合并集合实现动态CSS样式生成?
如何基于breakpoints和styles动态生成stylefy兼容的CSS样式Map
我需要实现一个merge方法,结合breakpoints与styles参数动态生成用于stylefy开发的CSS样式Map。最开始尝试用Specter来实现,但没能得到预期结果。
我尝试过的代码
(defn merge-style [breakpoints style] (let [media-queries (s/transform [s/ALL] #(hash-map :min-width (str %1 "px")) breakpoints)] breakpoints))
预期运行逻辑与输出
输入示例
(def breakpoints ["320px" "600px" "1280px"]) (def style {:padding-top ["20px" "30px" "40px" "50px"] :margin "30px" }) (merge-style breakpoints style)
预期输出
{:padding-top "20px" :margin "30px" ::stylefy/media {{:min-width "320px"} {:padding-top "30px"} {:min-width "600px"} {:padding-top "40px"} {:min-width "1280px"} {:padding-top "50px"}} }
最终解决方案
我已经自行解决了这个问题,实现的函数如下:
(defn- get-media-queries [breakpoints styles] (let [base-style (s/transform [s/MAP-VALS] #(%1 0) styles) styles-maps (s/setval [s/MAP-VALS empty?] s/NONE (s/setval [s/MAP-VALS s/FIRST] s/NONE styles)) styles-list (map (fn [[key val]] (map #(hash-map key %1) val)) styles-maps) styles-final (apply vdu/merge-maps styles-list) breaks (map #(hash-map :min-width %1) breakpoints) styles-merged (into {} (mapv vector breaks styles-final))] (assoc base-style ::stylefy/media styles-merged)))
这个函数的核心逻辑大概是这样:
- 先从传入的styles里提取基础样式(也就是每个样式数组的第一个元素)
- 移除基础样式后,处理剩余的响应式样式部分,把它们转换成对应断点的样式Map列表
- 将断点转换为
{:min-width "xxx"}格式的媒体查询条件 - 把媒体查询条件和对应的响应式样式一一配对,生成stylefy要求的
::stylefy/media字段内容 - 最后把媒体查询部分合并到基础样式中,得到最终可用的样式Map
内容的提问来源于stack exchange,提问作者pntripathi9417
相关产品推荐
相关产品推荐

