Clojurescript/OM 通过刷新保持应用程序状态
Clojurescript/OM persist app-state through refresh
我遵循了 OM's github Basic Tutorial 上的基本教程,这是一个简单的表单,可以修改存储在应用程序状态中的联系人数组,但是,这些修改是 'reset' 在页面刷新时。
如果我从当前 app-state
中删除 3 个人并刷新,这 3 个人将再次出现在 app-state
中。
代码与教程相同,但我 post 无论如何:
(ns ^:figwheel-always om-tut.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[cljs.core.async :refer [put! chan <!]]
[clojure.data :as data]
[clojure.string :as string]))
(enable-console-print!)
(println "Edits to this text should show up in your developer console.")
;; define your app data so that it doesn't get over-written on reload
(defonce app-state
(atom
{:contacts
[{:first "Ben" :last "Bitdiddle" :email "benb@mit.edu"}
{:first "Alyssa" :middle-initial "P" :last "Hacker" :email "aphacker@mit.edu"}
{:first "Eva" :middle "Lu" :last "Ator" :email "eval@mit.edu"}
{:first "Louis" :last "Reasoner" :email "prolog@mit.edu"}
{:first "Cy" :middle-initial "D" :last "Effect" :email "bugs@mit.edu"}
{:first "Lem" :middle-initial "E" :last "Tweakit" :email "morebugs@mit.edu"}]}))
(defn middle-name [{:keys [middle middle-initial]}]
(cond
middle (str " " middle)
middle-initial (str " " middle-initial ".")))
(defn display-name [{:keys [first last] :as contact}]
(str last ", " first (middle-name contact)))
(defn contact-view [contact owner]
(reify
om/IRenderState
(render-state [this {:keys [delete]}]
(dom/li nil
(dom/span nil (display-name contact))
(dom/button #js {:onClick (fn [e] (put! delete @contact))} "Delete")))))
(defn handle-change [e owner {:keys [text]}]
(let [value (.. e -target -value)]
(if-not (re-find #"[0-9]" value)
(om/set-state! owner :text value)
(om/set-state! owner :text text))))
(defn parse-contact [contact-str]
(let [[first middle last :as parts] (string/split contact-str #"\s+")
[first last middle] (if (nil? last) [first middle] [first last middle])
middle (when middle (string/replace middle "." ""))
c (if middle (count middle) 0)]
(when (>= (count parts) 2)
(cond-> {:first first :last last}
(== c 1) (assoc :middle-initial middle)
(>= c 2) (assoc :middle middle)))))
(defn add-contact [data owner]
(let [new-contact (-> (om/get-node owner "new-contact")
.-value
parse-contact)]
(when new-contact
(om/transact! data :contacts #(conj % new-contact))
(om/set-state! owner :text ""))))
(defn contacts-view [data owner]
(reify
om/IInitState
(init-state [_]
{:delete (chan)
:text ""})
om/IWillMount
(will-mount [_]
(let [delete (om/get-state owner :delete)]
(go (loop []
(let [contact (<! delete)]
(om/transact! data :contacts
(fn [xs] (vec (remove #(= contact %) xs))))
(recur))))))
om/IRenderState
(render-state [this state]
(dom/div nil
(dom/h2 nil "Contact list")
(apply dom/ul nil
(om/build-all contact-view (:contacts data)
{:init-state state}))
(dom/div nil
(dom/input
#js {:type "text" :ref "new-contact" :value (:text state)
:onChange #(handle-change % owner state)})
(dom/button #js {:onClick #(add-contact data owner)} "Add contact"))))))
(om/root contacts-view app-state
{:target (. js/document (getElementById "contacts"))})
(defn on-js-reload []
;; optionally touch your app-state to force rerendering depending on
;; your application
;; (swap! app-state update-in [:__figwheel_counter] inc)
)
客户端上的数据必须保存在服务器上或本地存储中。刷新 browser/reloading 浏览器与从头开始一样。所以,你拥有的任何数据都消失了,除非你坚持它。
我遵循了 OM's github Basic Tutorial 上的基本教程,这是一个简单的表单,可以修改存储在应用程序状态中的联系人数组,但是,这些修改是 'reset' 在页面刷新时。
如果我从当前 app-state
中删除 3 个人并刷新,这 3 个人将再次出现在 app-state
中。
代码与教程相同,但我 post 无论如何:
(ns ^:figwheel-always om-tut.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[cljs.core.async :refer [put! chan <!]]
[clojure.data :as data]
[clojure.string :as string]))
(enable-console-print!)
(println "Edits to this text should show up in your developer console.")
;; define your app data so that it doesn't get over-written on reload
(defonce app-state
(atom
{:contacts
[{:first "Ben" :last "Bitdiddle" :email "benb@mit.edu"}
{:first "Alyssa" :middle-initial "P" :last "Hacker" :email "aphacker@mit.edu"}
{:first "Eva" :middle "Lu" :last "Ator" :email "eval@mit.edu"}
{:first "Louis" :last "Reasoner" :email "prolog@mit.edu"}
{:first "Cy" :middle-initial "D" :last "Effect" :email "bugs@mit.edu"}
{:first "Lem" :middle-initial "E" :last "Tweakit" :email "morebugs@mit.edu"}]}))
(defn middle-name [{:keys [middle middle-initial]}]
(cond
middle (str " " middle)
middle-initial (str " " middle-initial ".")))
(defn display-name [{:keys [first last] :as contact}]
(str last ", " first (middle-name contact)))
(defn contact-view [contact owner]
(reify
om/IRenderState
(render-state [this {:keys [delete]}]
(dom/li nil
(dom/span nil (display-name contact))
(dom/button #js {:onClick (fn [e] (put! delete @contact))} "Delete")))))
(defn handle-change [e owner {:keys [text]}]
(let [value (.. e -target -value)]
(if-not (re-find #"[0-9]" value)
(om/set-state! owner :text value)
(om/set-state! owner :text text))))
(defn parse-contact [contact-str]
(let [[first middle last :as parts] (string/split contact-str #"\s+")
[first last middle] (if (nil? last) [first middle] [first last middle])
middle (when middle (string/replace middle "." ""))
c (if middle (count middle) 0)]
(when (>= (count parts) 2)
(cond-> {:first first :last last}
(== c 1) (assoc :middle-initial middle)
(>= c 2) (assoc :middle middle)))))
(defn add-contact [data owner]
(let [new-contact (-> (om/get-node owner "new-contact")
.-value
parse-contact)]
(when new-contact
(om/transact! data :contacts #(conj % new-contact))
(om/set-state! owner :text ""))))
(defn contacts-view [data owner]
(reify
om/IInitState
(init-state [_]
{:delete (chan)
:text ""})
om/IWillMount
(will-mount [_]
(let [delete (om/get-state owner :delete)]
(go (loop []
(let [contact (<! delete)]
(om/transact! data :contacts
(fn [xs] (vec (remove #(= contact %) xs))))
(recur))))))
om/IRenderState
(render-state [this state]
(dom/div nil
(dom/h2 nil "Contact list")
(apply dom/ul nil
(om/build-all contact-view (:contacts data)
{:init-state state}))
(dom/div nil
(dom/input
#js {:type "text" :ref "new-contact" :value (:text state)
:onChange #(handle-change % owner state)})
(dom/button #js {:onClick #(add-contact data owner)} "Add contact"))))))
(om/root contacts-view app-state
{:target (. js/document (getElementById "contacts"))})
(defn on-js-reload []
;; optionally touch your app-state to force rerendering depending on
;; your application
;; (swap! app-state update-in [:__figwheel_counter] inc)
)
客户端上的数据必须保存在服务器上或本地存储中。刷新 browser/reloading 浏览器与从头开始一样。所以,你拥有的任何数据都消失了,除非你坚持它。