Skip to content

Instantly share code, notes, and snippets.

@MrNice
Created June 3, 2015 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrNice/42cf8f97e53844df1e2b to your computer and use it in GitHub Desktop.
Save MrNice/42cf8f97e53844df1e2b to your computer and use it in GitHub Desktop.
Up front, the major differences between CLJS & Polymer versions
1. Polymer version is easier to load asynchronously; it brings its own stylesheet
2. CLJS version uses a `map`, doesn't need special inner template
3. CLJS version data flow is clearer, once one accepts the reagent/atom
4. CLJS version doesn't need the first template, as one simply calls the function as needed
5. Polymer version needs the dom-module tag and an id, CLJS doesn't
6. I have no idea what the performance difference between these components is. Hiccup -> HTML is an extra conversion, but so is HTML -> JS -> HTML.
Altogether, there aren't very many differences between these a Reagent component and a Polymer component.
Both compose logical view units, for example contact-card inside of friend-item (which of course is just the inner template).
Both have some notion of Data Binding to the view layer. It is simpler to see where the data is coming from in the reagent form, though, as it is defined completely independently of the view layer.
NOTE: The Reagent version initially renders nothing, as the firebase-collection is empty. We don't need a template to hide markup for later, or for Polymer dom-repeat.
Parting words:
The ClojureScript version is better. It is is prettier and NOT a DSL. For example, `<template is="dom-repeat" items="{{data}}">` is a special case, whereas `(map friend-item @users)` is pure ClojureScript. Reagent view layers have access to all of Clojure, and therefore can succinctly express complicated logic. Investing in ClojureScript, a language, is better than investing in curated DSLs.
Also, CLJS version has a more understandable data-flow. Clojure has well understood lexical scoping rules for accessing variable. I don't know what Polymer would do if the <firebase-collection> appeared AFTER the inner template (probably fail). Also, Polymer automatically labels collection elements "item".
<dom-module id="friend-list">
<link rel="import" type="css" href="friend-list.css">
<template>
<firebase-collection data="{{data}}"
location="https://users1.firebaseio.com/users">
</firebase-collection>
<template is="dom-repeat" items="{{data}}">
<contact-card starred="{{item.starred}}">
<img src="{{item.img}}" alt="{{item.name}}">
<span>{{item.name}}</span>
</contact-card>
</template>
</template>
</dom-module>
<!-- 414 non-whitespace chars -->
;; Assume firebase-collection returns a reagent/atom or similar
(def users (firebase-collection "https://users1.firebaseio.com/users"))
(defn friend-item [{:keys [starred img name]}]
[contact-card {:starred starred}
[:img {:src img :alt name}]
[:span name]])
(defn friend-list [users]
[:div {:class "friend-list"}]
(map friend-item @users)])
;; 262 non-whitespace chars
;; With CSS
(defn friend-list [users]
[:div {:class "friend-list"}]
;; This can be added here, but I've never used CLJS w/ Asynchronously loaded CSS, so idk what Gotcha's exist
[:link {:rel "import" :type "css" :href "friend-list.css"}]
(map friend-item @users)])
;; 59 more characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment