Refactor template code

- Use two types to store native and hiccup data
- Rename comp to component so cljs.core/comp is not shadowd
- Use className instead of class property
- Rename name property to tag
- Use static properties for React key

Use of static properties in this and other commits shrinks test-suite
output size by 2-3kB.
This commit is contained in:
Juho Teperi 2018-04-19 19:45:13 +03:00
parent 7482b2821e
commit 9c9825c289
2 changed files with 62 additions and 70 deletions

View File

@ -207,7 +207,7 @@
nil))
(defn get-wrapper [key f name]
(defn get-wrapper [key f]
(let [wrap (custom-wrapper key f)]
(when (and wrap f)
(assert-callable f))
@ -239,33 +239,33 @@
legacy-render (nil? render-fun)
render-fun (or render-fun
(:render fmap))
name (str (or (:displayName fmap)
display-name (str (or (:displayName fmap)
(util/fun-name render-fun)))
name (case name
display-name (case display-name
"" (str (gensym "reagent"))
name)
fmap (reduce-kv (fn [m k v]
(assoc m k (get-wrapper k v name)))
{} fmap)]
(assoc fmap
:displayName name
:autobind false
:cljsLegacyRender legacy-render
:reagentRender render-fun
:render (:render static-fns))))
(defn map-to-js [m]
(reduce-kv (fn [o k v]
(doto o
(gobj/set (name k) v)))
#js{} m))
display-name)
obj #js {}]
;; React lifecycle properties are added to object using
;; gobj/set so the names are never mangled. This will
;; probably require externs with npm to work.
(reduce-kv (fn [obj k v]
(doto obj
(gobj/set (name k) (get-wrapper k v))))
obj
(dissoc fmap :render :reagentRender :displayName :componentFunction))
;; These can be manged, if property is not mentioned in the extern.
(set! (.-displayName obj) display-name)
(set! (.-autobind obj) false)
(set! (.-cljsLegacyRender obj) legacy-render)
(set! (.-reagentRender obj) render-fun)
(set! (.-render obj) (:render static-fns))
obj))
(defn cljsify [body]
(-> body
camelify-map-keys
add-obligatory
wrap-funs
map-to-js))
wrap-funs))
(defn create-class [body]
{:pre [(map? body)]}

View File

@ -17,7 +17,7 @@
from a tag name."}
re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?")
(deftype NativeWrapper [])
(deftype NativeWrapper [tag id className])
;;; Common utilities
@ -100,13 +100,6 @@
(apply x args))
:else (clj->js x)))
(defn oset [o k v]
(doto (if (nil? o) #js {} o)
(gobj/set k v)))
(defn oget [o k]
(if (nil? o) nil (gobj/get o k)))
(defn set-id-class
"Takes the id and class from tag keyword, and adds them to the
other props. Parsed tag is JS object with :id and :class properties."
@ -263,10 +256,10 @@
:component-did-update input-component-set-value
:component-will-unmount input-unmount
:reagent-render
(fn [argv comp jsprops first-child]
(fn [argv component jsprops first-child]
(let [this comp/*current-component*]
(input-render-setup this jsprops)
(make-element argv comp jsprops first-child)))})
(make-element argv component jsprops first-child)))})
(defn reagent-input
[]
@ -277,18 +270,19 @@
;;; Conversion from Hiccup forms
(deftype HiccupTag [tag id className custom])
(defn parse-tag [hiccup-tag]
(let [[tag id class] (->> hiccup-tag name (re-matches re-tag) next)
class (when-not (nil? class)
(string/replace class #"\." " "))]
(assert tag (str "Invalid tag: '" hiccup-tag "'"
(comp/comp-name)))
#js {:name tag
:id id
:class class
(let [[tag id className] (->> hiccup-tag name (re-matches re-tag) next)
className (when-not (nil? className)
(string/replace className #"\." " "))]
(assert tag (str "Invalid tag: '" hiccup-tag "'" (comp/comp-name)))
(->HiccupTag tag
id
className
;; Custom element names must contain hyphen
;; https://www.w3.org/TR/custom-elements/#custom-elements-core-concepts
:custom (not= -1 (.indexOf tag "-"))}))
(not= -1 (.indexOf tag "-")))))
(defn try-get-key [x]
;; try catch to avoid clojurescript peculiarity with
@ -307,7 +301,8 @@
(defn reag-element [tag v]
(let [c (comp/as-class tag)
jsprops #js {:argv v}]
jsprops #js {}]
(set! (.-argv jsprops) v)
(when-some [key (key-from-vec v)]
(set! (.-key jsprops) key))
(react/createElement c jsprops)))
@ -315,19 +310,16 @@
(defn fragment-element [argv]
(let [props (nth argv 1 nil)
hasprops (or (nil? props) (map? props))
jsprops (convert-prop-value (if hasprops props))
jsprops (or (convert-prop-value (if hasprops props))
#js {})
first-child (+ 1 (if hasprops 1 0))]
(when-some [key (key-from-vec argv)]
(oset jsprops "key" key))
(set! (.-key jsprops) key))
(make-element argv react/Fragment jsprops first-child)))
(defn adapt-react-class
[c]
(let [x (->NativeWrapper)]
(set! (.-name x) c)
(set! (.-id x) nil)
(set! (.-class x) nil)
x))
(->NativeWrapper c nil nil))
(def tag-name-cache #js{})
@ -339,20 +331,20 @@
v)))
(defn native-element [parsed argv first]
(let [comp (.-name parsed)
(let [component (.-tag parsed)
props (nth argv first nil)
hasprops (or (nil? props) (map? props))
jsprops (convert-props (if hasprops props) parsed)
jsprops (or (convert-props (if hasprops props) parsed)
#js {})
first-child (+ first (if hasprops 1 0))]
(if (input-component? comp)
(-> [(reagent-input) argv comp jsprops first-child]
(if (input-component? component)
(-> [(reagent-input) argv component jsprops first-child]
(with-meta (meta argv))
as-element)
(let [key (-> (meta argv) get-key)
p (if (nil? key)
jsprops
(oset jsprops "key" key))]
(make-element argv comp p first-child)))))
(do
(when-some [key (-> (meta argv) get-key)]
(set! (.-key jsprops) key))
(make-element argv component jsprops first-child)))))
(defn str-coll [coll]
(if (dev?)
@ -379,12 +371,12 @@
pos (.indexOf n ">")]
(case pos
-1 (native-element (cached-parse n) v 1)
0 (let [comp (nth v 1 nil)]
;; Support [:> comp ...]
0 (let [component (nth v 1 nil)]
;; Support [:> component ...]
(assert (= ">" n) (hiccup-err v "Invalid Hiccup tag"))
(assert (or (string? comp) (fn? comp))
(assert (or (string? component) (fn? component))
(hiccup-err v "Expected React component in"))
(native-element #js{:name comp} v 2))
(native-element (->HiccupTag component nil nil nil) v 2))
;; Support extended hiccup syntax, i.e :div.bar>a.foo
;; Apply metadata (e.g. :key) to the outermost element.
;; Metadata is probably used only with sequeneces, and in that case
@ -461,12 +453,12 @@
;; ;; "_store" (js-obj)
;; )))
(defn make-element [argv comp jsprops first-child]
(defn make-element [argv component jsprops first-child]
(case (- (count argv) first-child)
;; Optimize cases of zero or one child
0 (react/createElement comp jsprops)
0 (react/createElement component jsprops)
1 (react/createElement comp jsprops
1 (react/createElement component jsprops
(as-element (nth argv first-child nil)))
(.apply react/createElement nil
@ -474,4 +466,4 @@
(when (>= k first-child)
(.push a (as-element v)))
a)
#js[comp jsprops] argv))))
#js[component jsprops] argv))))