Experiment with skipping wrappers for native React components

This should make initial rendering a bit faster, as well as cases
where many components change simultaneously.

It should also lead to slightly less memory use.

The drawback is that native components no longer use
shouldComponentUpdate, and so requires more conversion from cljs
to js values – but this is now quite fast anyway.
This commit is contained in:
Dan Holmsand 2014-11-30 11:29:36 +01:00
parent 9bfbbc1ae2
commit 5fb9db3b14
1 changed files with 31 additions and 14 deletions

View File

@ -69,14 +69,15 @@
(str class " " old) (str class " " old)
class)))))) class))))))
(defn convert-props [props id-class] (defn convert-props [props id-class allow-key]
(cond (cond
(and (empty? props) (nil? id-class)) nil (and (empty? props) (nil? id-class)) nil
(identical? (type props) js/Object) props (identical? (type props) js/Object) props
:else (let [objprops :else (let [objprops
(reduce-kv (fn [o k v] (reduce-kv (fn [o k v]
(let [pname (cached-prop-name k)] (let [pname (cached-prop-name k)]
(if-not (identical? pname "key") (if (or allow-key
(not (identical? pname "key")))
;; Skip key, it is set by parent ;; Skip key, it is set by parent
(aset o pname (convert-prop-value v)))) (aset o pname (convert-prop-value v))))
o) o)
@ -139,7 +140,7 @@
argv (.' inprops :argv) argv (.' inprops :argv)
props (nth argv 1 nil) props (nth argv 1 nil)
hasprops (or (nil? props) (map? props)) hasprops (or (nil? props) (map? props))
jsprops (convert-props (if hasprops props) id-class)] jsprops (convert-props (if hasprops props) id-class false)]
(when-not (nil? input-setup) (when-not (nil? input-setup)
(input-setup this jsprops)) (input-setup this jsprops))
(make-element argv comp jsprops (make-element argv comp jsprops
@ -203,22 +204,38 @@
(util/cache-react-class tag (wrap-component tag nil nil)) (util/cache-react-class tag (wrap-component tag nil nil))
(fn-to-class tag)))))) (fn-to-class tag))))))
(def cached-parse (util/memoize-1 parse-tag))
(defn native-element [tag argv]
(when (hiccup-tag? tag)
(let [[comp id-class] (cached-parse tag)]
(when-not (input-component? comp)
(let [props (nth argv 1 nil)
hasprops (or (nil? props) (map? props))
jsprops (convert-props (if hasprops props) id-class true)]
(make-element argv comp jsprops
(if hasprops 2 1)))))))
(defn get-key [x] (defn get-key [x]
(when (map? x) (get x :key))) (when (map? x) (get x :key)))
(defn vec-to-comp [v] (defn vec-to-comp [v]
(assert (pos? (count v)) "Hiccup form should not be empty") (assert (pos? (count v)) "Hiccup form should not be empty")
(assert (valid-tag? (nth v 0)) (let [tag (nth v 0)]
(str "Invalid Hiccup form: " (pr-str v))) (assert (valid-tag? tag)
(let [c (as-class (nth v 0)) (str "Invalid Hiccup form: " (pr-str v)))
jsprops #js{:argv v}] (let [ne (native-element tag v)]
(let [k (-> v meta get-key) (if (some? ne)
k' (if (nil? k) ne
(-> v (nth 1 nil) get-key) (let [c (as-class (nth v 0))
k)] jsprops #js{:argv v}]
(when-not (nil? k') (let [k (-> v meta get-key)
(.! jsprops :key k'))) k' (if (nil? k)
(.' js/React createElement c jsprops))) (-> v (nth 1 nil) get-key)
k)]
(when-not (nil? k')
(.! jsprops :key k')))
(.' js/React createElement c jsprops))))))
(def seq-ctx #js{}) (def seq-ctx #js{})