You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ClojureScript中如何评估列表并批量定义Material-UI组件?

问题1:评估quoted的def表达式,让one的值变为1

在ClojureScript中,你可以用cljs.core/eval来执行这个quoted的定义表达式。和Clojure不同的是,CLJS的eval受编译环境影响(比如高级优化模式下会有更多限制),但在开发环境或者简单场景下完全够用。

直接运行这段代码就能实现需求:

(def defining-list `(def one 1))
(cljs.core/eval defining-list)

;; 测试验证,会输出1
(println one)

注意:eval默认会在当前命名空间执行,所以one会被定义在你当前的命名空间下。如果需要在特定命名空间执行,你可以先切换命名空间或者指定命名空间来评估。


问题2:批量定义Material-UI组件(无需宏)

你之前的doseq代码只是生成了def表达式的列表,但没有实际执行它们。不用宏也不用eval的话,推荐用cljs.core/intern来动态在当前命名空间创建变量——这是CLJS里更安全、更符合惯用写法的动态定义方式,还能避免eval带来的兼容性和安全问题。

这里是完整的实现代码:

;; 确保已经引入reagent的adapt-react-class
(require '[reagent.core :as r])

(def material-ui-tags '[AppBar Avatar Backdrop])

(doseq [component material-ui-tags]
  (let [;; 把组件名转成kebab-case的符号(比如AppBar → app-bar)
        kebab-name (-> (name component)
                       (clojure.string/replace #"([A-Z])" "-$1")
                       clojure.string/lower-case
                       (clojure.string/replace #"^-" ""))
        kebab-symbol (symbol kebab-name)
        ;; 获取MaterialUI上的原生React组件
        raw-component (aget js/MaterialUI (name component))
        ;; 用reagent适配成CLJS可用的组件
        cljs-component (r/adapt-react-class raw-component)]
    ;; 在当前命名空间定义这个符号,绑定到适配后的组件
    (intern *ns* kebab-symbol cljs-component)))

如果你的项目里已经有现成的->kebab-case函数(比如来自clojure.string或者第三方工具库),可以直接替换掉上面的字符串处理逻辑,代码会更简洁:

(doseq [component material-ui-tags]
  (let [kebab-symbol (symbol (->kebab-case component))
        cljs-component (r/adapt-react-class (aget js/MaterialUI (name component)))]
    (intern *ns* kebab-symbol cljs-component)))

执行完这段代码后,你就能直接使用app-bar、avatar、backdrop这些符号了,和手动逐个定义的效果完全一致。


内容的提问来源于stack exchange,提问作者m-arch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:08:31