shadow-cljs clojurescript Cookbook
虽然有官网api文档, 虽然有https://cljs.info/cheatsheet/, 虽然有clojure的书和clojure开发经验.但总还是有一些磕磕绊绊.
自己写个cookbook,备查.
1. REPL报错 already started
npx shadow-cljs stop
calva命令里缺乏停止/重启 REPL
只能自己手动停止, 然后再用calva启动一个就OK
2 .用字符串函数名,调用 js定义的window.XXX 函数
应该叫反射吧,不懂.反正搜索半天,都不work
最后这样
(defn get-fn [fn-name]
(js/eval (.format "window.%s" fn-name)))
简单说,利用 cljs的js/eval, 用js的eval函数,对"window.XXX"求值,就得到了函数, 然后就可以调用了. 不是利用cljs的机制,而是利用寄生平台js 引擎的机制. 毕竟js也是参考lisp,有eval,比较functional的嘛.
3. shadow-cljs 依赖本地js文件
比如 XXX.min.js 或者自己写的单个js文件.
希望shadow-cljs把这些和自己的cljs一起作为src打包成1个bundle
文件这样放:
src/js 下 assets文件夹下 放别人开发好的js库, 自己写的config.js放点全局变量啥的
shadow-cljs.edn 这样写:
;; shadow-cljs configuration {:source-paths ["src/dev" "src/main" "src/test"] :dependencies [] :dev-http {8080 "public"} :builds {:frontend {:target :browser :modules {:main {:init-fn frontend.app/init} } :js-options {:resolve {"stomp" {:target :file :file "src/js/assets/stomp.umd.min.js"} "config" {:target :file :file "src/js/config.js"} } }}} }
:file的路径注意从工程根目录开始写起
app.cljs里这样写
(ns frontend.app (:require [frontend.util :refer (console-log)] [stomp] [config :refer [para_stomp]] ) )
4 js object作为函数参数
图省事,直接吧参数放js里了, 最好还是用js去组装
也有clj->js函数可以吧clojure数据结构转成js object,但没试验.
5 调用js 对象的方法 提示 warning infer XXX
Cannot infer target type in expression (. fnname obj)
尤其是 这个obj 的构造函数是 js里声明, obj 是(new )出来的
要声明这个obj的类型注解
比如new 一个js的对象,然后调用它的方法.
const client_stomp = new Client() client_stomp.activate()
cljs这样写:
(ns frontend.app (:require [frontend.util :refer (console-log)] [stomp] [config :refer [para_stomp]] ) ) (def ^stomp/Client client-stomp) ;增加类型注解 (defn init [] (console-log "Hello World") (console-log para_stomp) (set! client-stomp (new stomp/Client para_stomp)) (console-log client-stomp) (aset client-stomp "onConnect" (fn [frame] (console-log "stomp connected"))) ;; (console-log client-stomp) (.activate client-stomp ) )
声明时必须加上类型注解 ^stomp/Client