项目作者: metametadata

项目描述 :
ClojureScript application framework.
高级语言: Clojure
项目地址: git://github.com/metametadata/carry.git
创建时间: 2016-02-18T17:50:32Z
项目社区:https://github.com/metametadata/carry

开源协议:MIT License

下载


Carry

ClojureScript single-page application framework inspired by
re-frame,
Elm Architecture,
Redux and
Cerebral.

Carry provides a structure for making GUI application code easier to modify, debug, test and be worked on by multiple programmers.

The core of the framework is a simple state management library.
UI bindings, routing, debugger, etc. are implemented as separate optional packages.

Clojars Project
Gitter
Slack

Status

Stable. Was used in production.

I now focus on the successor Aide framework instead.

Features

Pattern

Carry enforces:

  • Separation of presentation code.
  • Events as first-class citizens.
  • Splitting event handling code into side-effectful and “pure” model updating phases.
  • Storing model in a single observable atom.

It also advises to decouple view and view model code in the presentation layer:

pattern

  • An app is defined by its initial model value, signal handler and action handler.
  • All app state is stored inside a single model atom.
  • Anyone can read model value at any given time and subscribe to its changes.
  • Signal handler performs side effects and dispatches actions.
  • Anyone can dispatch a new signal: signal handler, views, timers, etc.
  • Typically UI layer dispatches signals on UI events and subscribes to model changes to redraw the GUI when needed.
  • Model can be modified only by dispatching actions.
  • Only signal handler can dispatch actions.
  • Action handler is a pure function which returns a new model value based on an incoming action.

Example (counter app)

Demo,
Source code

HTML:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. <title>Carry • Counter</title>
  7. <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  8. </head>
  9. <body>
  10. <div id="root"></div>
  11. <script src="js/compiled/frontend.js" type="text/javascript"></script>
  12. </body>
  13. </html>

Main file:

  1. (ns app.core
  2. (:require [counter.core :as counter]
  3. [carry.core :as carry]
  4. [carry-reagent.core :as carry-reagent]
  5. [reagent.core :as r]))
  6. (let [app (carry/app counter/blueprint)
  7. [_ app-view] (carry-reagent/connect app counter/view-model counter/view)]
  8. (r/render app-view (.getElementById js/document "root"))
  9. ((:dispatch-signal app) :on-start))

UI (using Reagent and carry-reagent):

  1. (ns counter.core
  2. (:require [cljs.core.match :refer-macros [match]]
  3. [reagent.ratom :refer [reaction]]))
  4. (defn view-model
  5. [model]
  6. {:counter (reaction (str "#" (:val @model)))})
  7. (defn view
  8. [{:keys [counter] :as _view-model} dispatch]
  9. [:p
  10. @counter " "
  11. [:button {:on-click #(dispatch :on-increment)} "+"] " "
  12. [:button {:on-click #(dispatch :on-decrement)} "-"] " "
  13. [:button {:on-click #(dispatch :on-increment-if-odd)} "Increment if odd"] " "
  14. [:button {:on-click #(dispatch :on-increment-async)} "Increment async"]])

Blueprint:

  1. (def -initial-model {:val 0})
  2. (defn -on-signal
  3. [model signal _dispatch-signal dispatch-action]
  4. (match signal
  5. :on-start nil
  6. :on-stop nil
  7. :on-increment
  8. (dispatch-action :increment)
  9. :on-decrement
  10. (dispatch-action :decrement)
  11. :on-increment-if-odd
  12. (when (odd? (:val @model))
  13. (dispatch-action :increment))
  14. :on-increment-async
  15. (.setTimeout js/window #(dispatch-action :increment) 1000)))
  16. (defn -on-action
  17. [model action]
  18. (match action
  19. :increment (update model :val inc)
  20. :decrement (update model :val dec)))
  21. (def blueprint {:initial-model -initial-model
  22. :on-signal -on-signal
  23. :on-action -on-action})

Packages

UI Bindings

Middleware

Documentation

More information can be found at the project site:

License

Copyright © 2016 Yuri Govorushchenko.

Released under an MIT license.