ClojureScript Notes
- Cheatsheet
- Google Closure Library
- Links
- Importing
- javascript to cljs
- cljs to javascript
- Namespaces
- String to Integer
- Random, Unique Symbol/Variable Name
- Binding
- Window and Document
- 3 Forms of Reagent Components
Cheatsheet
Google Closure Library
Links
- Including third party js libraries and external javascript in clojurescript
- Javascript Libraries Packaged as Jars - cljsjs
- Clojurescript and React Native
- Javascript Interop
- Two ways to access Properties
- DevCards
- Closure Cheat Sheet
Importing
There's a subtle difference between import
and require
. If you want to import a Closure Class, then use import
. When you want to import javascript functions from a library, use require
(ns async-tut1.core
(:require [goog.events :refer [listen] :as ev])
(:import [goog.net XhrIo]))
javascript to cljs
(js->clj {:foo "bar"})
cljs to javascript
(clj->js {:foo "bar"})
Or, you can use the #js
shorthand
#js {:foo "bar}
# InteropAccessing Javascript Properties
.-
operates on symbols. Advanced compile renames symbols. If you use only .-
and set!
then no problem (and you get nice compiler optimizations).
(.-prop obj) ;; obj.prop
(.. js/obj -prop1 -prop2) ;; obj.prop1.prop2
aget
operates on names. Advanced compile ignores names. Lose some optimizations, but names are save to use from javascript
(aget js/obj "prop1" "prop2") ;; obj["prop1"]["prop2"]
Setting Property Values
set!
corresponds to .-
(set! (.-prop1 obj) val) ;; obj.prop1 = val
Note that set!
operates on symbols. Advanced compiler renames symbols.
aset
corresponds to aget
(aset js/obj "prop1" "prop2" val) ;; obj["prop1"]["prop2"] = val
Note that aset
operates on names. Advanced compiler leaves names intact.
Namespaces
Change namespaces from the clojurescript repl
(in-ns 'path.to.namespace)
Load cljs files from repl. load-namespace
will also load dependencies
(load-namespace "path.to.namespace")
String to Integer
(js/parseInt "10")
Random, Unique Symbol/Variable Name
(gensym)
;; or
(random-uuid)
Binding this
Use this-as
Window and Document
js/window, js/document3 Forms of Reagent Components
Form 1:
(defn greet
[name] ;; data coming in is a string
[:div "Hello " name]) ;; returns Hiccup (HTML)
Form 2:
(defn timer-component []
(let [seconds-elapsed (reagent/atom 0)] ;; setup, and local state
(fn [] ;; inner, render function is returned
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:div "Seconds Elapsed: " @seconds-elapsed])))
(defn outer
[a b c] ;; <--- parameters
;; ....
(fn [a b c] ;; <--- forgetting to repeat them, is a rookie mistake
[:div
(str a b c)]))
Form 3:
(defn my-component
[x y z]
(let [some (local but shared state) ;; <-- closed over by lifecycle fns
can (go here)]
(reagent/create-class ;; <-- expects a map of functions
{:component-did-mount ;; the name of a lifecycle function
#(println "component-did-mount") ;; your implementation
:component-will-mount ;; the name of a lifecycle function
#(println "component-will-mount") ;; your implementation
;; other lifecycle funcs can go in here
:display-name "my-component" ;; for more helpful warnings & errors
:reagent-render ;; Note: is not :render
(fn [x y z] ;; remember to repeat parameters
[:div (str x " " y " " z)])})))