From 81da69697e737821d69c1caacf3b4fc4f986e32b Mon Sep 17 00:00:00 2001 From: Dan Holmsand Date: Mon, 10 Feb 2014 16:33:22 +0100 Subject: [PATCH] Move update batching to util --- src/reagent/core.cljs | 6 +-- src/reagent/impl/component.cljs | 76 +++-------------------------- src/reagent/impl/template.cljs | 6 +-- src/reagent/impl/util.cljs | 84 ++++++++++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 77 deletions(-) diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index 5529075..a7d440e 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -9,7 +9,7 @@ (def React tmpl/React) -(def is-client tmpl/isClient) +(def is-client util/isClient) (defn render-component "Render a Reagent component into the DOM. The first argument may be either a @@ -110,7 +110,7 @@ specially, like React's transferPropsTo." Note that this may not work in event handlers, since React.js does batching of updates there." [] - (comp/flush)) + (util/flush)) @@ -129,7 +129,7 @@ re-rendered." (defn next-tick "Run f using requestAnimationFrame or equivalent." [f] - (comp/next-tick f)) + (util/next-tick f)) (defn partial "Works just like clojure.core/partial, except that it is an IFn, and diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 2167704..b0149b2 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -1,9 +1,8 @@ (ns reagent.impl.component - (:refer-clojure :exclude [flush]) (:require [reagent.impl.template :as tmpl :refer [cljs-argv cljs-level React]] - [reagent.impl.util :as util] + [reagent.impl.util :as util :refer [cljs-level]] [reagent.ratom :as ratom] [reagent.debug :refer-macros [dbg prn]])) @@ -53,55 +52,6 @@ ;;; Rendering -(defn fake-raf [f] - (js/setTimeout f 16)) - -(def next-tick - (if-not tmpl/isClient - fake-raf - (let [w js/window] - (or (.-requestAnimationFrame w) - (.-webkitRequestAnimationFrame w) - (.-mozRequestAnimationFrame w) - (.-msRequestAnimationFrame w) - fake-raf)))) - -(defn compare-levels [c1 c2] - (- (-> c1 js-props (aget cljs-level)) - (-> c2 js-props (aget cljs-level)))) - -(defn run-queue [a] - ;; sort components by level, to make sure parents - ;; are rendered before children - (.sort a compare-levels) - (dotimes [i (alength a)] - (let [C (aget a i)] - (when (.-cljsIsDirty C) - (.forceUpdate C))))) - -(deftype RenderQueue [^:mutable queue ^:mutable scheduled?] - Object - (queue-render [this C] - (.push queue C) - (.schedule this)) - (schedule [this] - (when-not scheduled? - (set! scheduled? true) - (next-tick #(.run-queue this)))) - (run-queue [_] - (let [q queue] - (set! queue (array)) - (set! scheduled? false) - (run-queue q)))) - -(def render-queue (RenderQueue. (array) false)) - -(defn flush [] - (.run-queue render-queue)) - -(defn queue-render [C] - (set! (.-cljsIsDirty C) true) - (.queue-render render-queue C)) (defn do-render [C] (set! (.-cljsIsDirty C) false) @@ -128,20 +78,6 @@ (do-render C)) res))))) -(defn run-reactively [C run on-dirty] - (let [rat (.-cljsRatom C)] - (if (nil? rat) - (let [res (ratom/capture-derefed run C) - derefed (.-captured C)] - (when (and (not (nil? derefed)) - tmpl/isClient) - (set! (.-cljsRatom C) - (ratom/make-reaction run - :auto-run on-dirty - :derefed derefed))) - res) - (ratom/run rat)))) - ;;; Function wrapping @@ -227,10 +163,12 @@ (defn add-render [fun-map render-f] (assoc fun-map :cljsRender render-f - :render (fn [] - (this-as C - (run-reactively - C #(do-render C) #(queue-render C)))))) + :render (if util/isClient + (fn [] + (this-as C + (util/run-reactively + C #(do-render C) #(util/queue-render C)))) + (fn [] (this-as C (do-render C)))))) (defn wrap-funs [fun-map] (let [render-fun (or (:componentFunction fun-map) diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 4ed3419..273b00b 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -2,16 +2,14 @@ (ns reagent.impl.template (:require [clojure.string :as string] [reagent.impl.reactimport :as reactimport] - [reagent.impl.util :as util] + [reagent.impl.util :as util :refer [cljs-level]] [reagent.debug :refer-macros [dbg prn println log]])) (def React reactimport/React) (def cljs-argv "cljsArgv") -(def cljs-level "cljsLevel") -(def isClient (not (nil? (try (.-document js/window) - (catch js/Object e nil))))) +(def isClient util/isClient) (def dont-camel-case #{"aria" "data"}) diff --git a/src/reagent/impl/util.cljs b/src/reagent/impl/util.cljs index fc8b103..07a0198 100644 --- a/src/reagent/impl/util.cljs +++ b/src/reagent/impl/util.cljs @@ -1,5 +1,67 @@ (ns reagent.impl.util - (:require [reagent.debug :refer-macros [dbg]])) + (:refer-clojure :exclude [flush]) + (:require [reagent.debug :refer-macros [dbg]] + [reagent.ratom :as ratom])) + +(def isClient (not (nil? (try (.-document js/window) + (catch js/Object e nil))))) + +(def cljs-level "cljsLevel") + +;;; Update batching + +(defn fake-raf [f] + (js/setTimeout f 16)) + +(def next-tick + (if-not isClient + fake-raf + (let [w js/window] + (or (.-requestAnimationFrame w) + (.-webkitRequestAnimationFrame w) + (.-mozRequestAnimationFrame w) + (.-msRequestAnimationFrame w) + fake-raf)))) + +(defn compare-levels [c1 c2] + (- (-> c1 (aget "props") (aget cljs-level)) + (-> c2 (aget "props") (aget cljs-level)))) + +(defn run-queue [a] + ;; sort components by level, to make sure parents + ;; are rendered before children + (.sort a compare-levels) + (dotimes [i (alength a)] + (let [C (aget a i)] + (when (.-cljsIsDirty C) + (.forceUpdate C))))) + +(deftype RenderQueue [^:mutable queue ^:mutable scheduled?] + Object + (queue-render [this C] + (.push queue C) + (.schedule this)) + (schedule [this] + (when-not scheduled? + (set! scheduled? true) + (next-tick #(.run-queue this)))) + (run-queue [_] + (let [q queue] + (set! queue (array)) + (set! scheduled? false) + (run-queue q)))) + +(def render-queue (RenderQueue. (array) false)) + +(defn flush [] + (.run-queue render-queue)) + +(defn queue-render [C] + (set! (.-cljsIsDirty C) true) + (.queue-render render-queue C)) + + +;; Misc utilities (deftype partial-ifn [f args ^:mutable p] IFn @@ -35,6 +97,9 @@ (assert (map? p1)) (merge-style p1 (merge-class p1 (merge p1 p2)))))) + +;;; Helpers for shouldComponentUpdate + (def -not-found (js-obj)) (defn shallow-equal-maps [x y] @@ -71,3 +136,20 @@ (shallow-equal-maps (v1 1) (v2 1)))) (recur (inc n)) false))))))) + + +;; Render helper + +(defn run-reactively [C run on-dirty] + (let [rat (.-cljsRatom C)] + (if (nil? rat) + (let [res (ratom/capture-derefed run C) + derefed (.-captured C)] + (when (not (nil? derefed)) + (set! (.-cljsRatom C) + (ratom/make-reaction run + :auto-run on-dirty + :derefed derefed))) + res) + (ratom/run rat)))) +