Start experimenting with batched rendering with requestAnimationFrame

This commit is contained in:
Dan Holmsand 2014-01-27 13:37:59 +01:00
parent 68da921e35
commit eb381f13bb
5 changed files with 65 additions and 12 deletions

View File

@ -39,7 +39,8 @@
[:div.demo-example [:div.demo-example
[:a.demo-example-hide {:on-click (fn [e] [:a.demo-example-hide {:on-click (fn [e]
(.preventDefault e) (.preventDefault e)
(swap! showing not))} (swap! showing not)
false)}
(if @showing "hide" "show")] (if @showing "hide" "show")]
[:h3.demo-heading "Example "] [:h3.demo-heading "Example "]
(when @showing (when @showing

View File

@ -1,5 +1,5 @@
(defproject reagent "0.2.1" (defproject reagent "0.3.0-SNAPSHOT"
:url "http://github.com/holmsand/reagent" :url "http://github.com/holmsand/reagent"
:license {:name "MIT"} :license {:name "MIT"}
:description "A simple ClojureScript interface to React" :description "A simple ClojureScript interface to React"

View File

@ -1,6 +1,6 @@
(ns reagent.core (ns reagent.core
(:refer-clojure :exclude [partial atom]) (:refer-clojure :exclude [partial atom flush])
(:require-macros [reagent.debug :refer [dbg prn]]) (:require-macros [reagent.debug :refer [dbg prn]])
(:require [reagent.impl.template :as tmpl] (:require [reagent.impl.template :as tmpl]
[reagent.impl.component :as comp] [reagent.impl.component :as comp]
@ -105,6 +105,10 @@ specially, like React's transferPropsTo."
[defaults props] [defaults props]
(util/merge-props defaults props)) (util/merge-props defaults props))
(defn flush []
(comp/flush))
;; Ratom ;; Ratom

View File

@ -1,5 +1,6 @@
(ns reagent.impl.component (ns reagent.impl.component
(:refer-clojure :exclude [flush])
(:require [reagent.impl.template :as tmpl (:require [reagent.impl.template :as tmpl
:refer [cljs-props cljs-children React]] :refer [cljs-props cljs-children React]]
[reagent.impl.util :as util] [reagent.impl.util :as util]
@ -43,10 +44,46 @@
(defn set-props [C newprops] (defn set-props [C newprops]
(replace-props C (merge (get-props C) newprops))) (replace-props C (merge (get-props C) newprops)))
;;; Rendering
;;; Function wrapping (defn next-tick [f]
(if (.-requestAnimationFrame js/window)
(js/requestAnimationFrame f)
(js/setTimeout f 16)))
(defn run-queue [v]
(doseq [C v]
(when-not (.-cljsIsDirty C)
(dbg C))
(when (.-cljsIsDirty C)
(.forceUpdate C))))
(deftype RenderQueue [^:mutable queue ^:mutable scheduled?]
Object
(queue-render [this C]
(set! queue (conj queue C))
(.schedule this))
(schedule [this]
(when-not scheduled?
(set! scheduled? true)
(next-tick #(.run-queue this))))
(run-queue [_]
(let [q queue]
(set! queue (empty queue))
(set! scheduled? false)
(run-queue q))))
(def render-queue (RenderQueue. [] false))
(defn flush []
(.run-queue render-queue))
(defn queue-render [C]
(set! (.-cljsIsDirty C) true)
(.queue-render render-queue C))
(defn do-render [C f] (defn do-render [C f]
(set! (.-cljsIsDirty C) false)
(let [p (js-props C) (let [p (js-props C)
props (props-in-props p) props (props-in-props p)
children (aget p cljs-children) children (aget p cljs-children)
@ -66,10 +103,13 @@
(ratom/make-reaction (ratom/make-reaction
#(do-render C (.-cljsRenderFn C)) #(do-render C (.-cljsRenderFn C))
:auto-run (if tmpl/isClient :auto-run (if tmpl/isClient
#(.forceUpdate C) #(queue-render C)
identity)))) identity))))
(ratom/run (.-cljsRatom C))) (ratom/run (.-cljsRatom C)))
;;; Function wrapping
(defn custom-wrapper [key f] (defn custom-wrapper [key f]
(case key (case key
:getDefaultProps :getDefaultProps
@ -108,6 +148,7 @@
:componentWillUnmount :componentWillUnmount
(fn [C] (fn [C]
(ratom/dispose! (.-cljsRatom C)) (ratom/dispose! (.-cljsRatom C))
(set! (.-cljsIsDirty C) false)
(when f (f C))) (when f (f C)))
:render :render

View File

@ -95,27 +95,34 @@
(let [ran (atom 0) (let [ran (atom 0)
runs (running) runs (running)
val (atom 0) val (atom 0)
secval (atom 0)
v1 (reaction @val) v1 (reaction @val)
comp (fn [] comp (fn []
(swap! ran inc) (swap! ran inc)
[:div (str "val " @v1)])] [:div (str "val " @v1 @val @secval)])]
(with-mounted-component [comp] (with-mounted-component [comp]
(fn [C div] (fn [C div]
(swap! ran inc) (reagent/flush)
(is (not= runs (running))) (is (not= runs (running)))
(is (found-in #"val 0" div)) (is (found-in #"val 0" div))
(is (= 2 @ran)) (is (= 1 @ran))
(reset! secval 1)
(reset! secval 0)
(reset! val 1) (reset! val 1)
(reset! val 2)
(reset! val 1)
(reagent/flush)
(is (found-in #"val 1" div)) (is (found-in #"val 1" div))
(is (= 3 @ran)) (is (= 2 @ran))
;; should not be rendered ;; should not be rendered
(reset! val 1) (reset! val 1)
(reagent/flush)
(is (found-in #"val 1" div)) (is (found-in #"val 1" div))
(is (= 3 @ran)))) (is (= 2 @ran))))
(is (= runs (running))) (is (= runs (running)))
(is (= 3 @ran))))) (is (= 2 @ran)))))
(deftest init-state-test (deftest init-state-test
(when isClient (when isClient