pbk*_*hrv 3 clojurescript reagent re-frame
我有一个带有整数输入字段和两个按钮“+1”和“-1”的试剂组件。我想让用户能够:
另外,在使用重新框架时,我希望能够
我该怎么做?
总纲:
reset!中的值:on-change和:on-click为了与 re-frame 的 app db 集成,我们需要添加以下内容:
re-frame/dispatch在:on-change与:on-clickre-frame/subscribe 值存储在重新框架的应用程序数据库中的位置并相应地更新本地试剂原子让我们看一些代码,从试剂组件开始:
(defn integer-field [default-value]
(let [int-atom (atom default-value)]
(fn []
[:div
[:input {:type "text"
:value @int-atom
:on-change #(reset! int-atom (-> % .-target .-value))}]
[:button {:on-click #(adjust-int int-atom 1)} "+"]
[:button {:on-click #(adjust-int int-atom -1)}]])))
Run Code Online (Sandbox Code Playgroud)
诀窍是reset!每次我们收到一个:on-change事件时都在原子中,让试剂/反应负责重新渲染幕后的场。
另请注意,:on-click调用另一个adjust-int增加/减少字段原子值的函数。这里是:
(defn- adjust-int [int-atom delta]
(let [v (js/parseInt @int-atom)
valid? (not (js/Number.isNaN v))
new-v (+v delta)]
(when valid?
(reset! int-atom new-v))))
Run Code Online (Sandbox Code Playgroud)
这按原样工作。但是,如果我们决定在重新帧中存储整数值,我们确实需要更多代码。首先,让我们创建一个处理程序来存储它从数据库中的输入字段接收的值:
(re-frame/register-handler
:integer-input-field-updated
(fn [db [_ value]]
(assoc db :integer-value value)))
Run Code Online (Sandbox Code Playgroud)
(re-frame/dispatch :integer-input-field-updated value)除了reset!-ing 试剂原子之外,我们现在需要在每次输入字段的值发生变化时调用。让我们为它添加一个辅助函数:
(defn- store-int-value [int-atom value]
(reset! int-atom value)
(re-frame/dispatch :integer-input-field-updated value))
Run Code Online (Sandbox Code Playgroud)
我们现在需要调用这个函数,而不是reset!每次值准备好存储时调用。让我们adjust-int首先进行更改:
(defn- adjust-int [int-atom delta]
(let [v (js/parseInt @int-atom)
valid? (not (js/Number.isNaN v))
new-v (+v delta)]
(when valid?
(store-int-value int-atom new-v)))) ;; <---- changed
Run Code Online (Sandbox Code Playgroud)
让我们回顾一下到目前为止的内容:
我们需要一种方法来支持另一个方向的值流,从应用程序数据库到本地原子。我们可以连接一个订阅,对更改做出反应(:integer-value @db)并重置我们的本地原子。等等,这听起来像是某种循环,不是吗?让我们可视化流程:
:on-click(reset! int-atom) -> 重新渲染输入字段(dispatch [:integer-input-field-updated new-value])(assoc db :integer-value value)(reset! int-atom) -> 重新渲染输入字段那不酷。我们需要确保信息只在一个方向流动,这意味着改变:integer-value应该不会触发更改本地原子,但切换到本地原子也得到传播到:integer-value。基本上,我们的 UI 不应该对它自己发起的更新做出反应。我们可以通过在 db 中引入另一个键来实现这re-frame/subscribe一点,并强制所有:integer-value不是来自 UI 的更新都更新。让我们调用这个键:integer-value-input-field并为其创建一个子项和一个处理程序:
(re-frame/register-sub
:integer-field-input-value
(fn [db _]
(reaction (:integer-field-input-value @db))))
(re-frame/register-handler
:integer-value-updated ;; <--- for use by other parts of the app
(fn [db [_ value]]
(assoc db :integer-field value :integer-field-input-value value)))
Run Code Online (Sandbox Code Playgroud)
最后,让我们重构integer-field组件:
(defn integer-field [default-value]
(let [int-atom (atom default-value)
the-int (re-frame/subscribe [:integer-field-input-value])] ;; <--- source of truth
(fn []
(reset! int-atom @the-int) ;; <--- spread the truth
[:div
[:input {:type "text"
:value @int-atom
:on-change #(store-int-value int-atom(-> % .-target .-value))}]
[:button {:on-click #(adjust-int int-atom 1)} "+"]
[:button {:on-click #(adjust-int int-atom -1)}]])))
Run Code Online (Sandbox Code Playgroud)
现在,所有代码都集中在一个地方......
(re-frame/register-sub
:integer-field-input-value
(fn [db _]
(reaction (:integer-field-input-value @db))))
;; to be used by other parts of the app
(re-frame/register-handler
:integer-value-updated
(fn [db [_ value]]
(assoc db :integer-field value :integer-field-input-value value)))
;; to be used by the integer-field component
(re-frame/register-handler
:integer-input-field-updated
(fn [db [_ value]]
(assoc db :integer-value value)))
(defn- store-int-value [int-atom value]
(reset! int-atom value)
(re-frame/dispatch :integer-input-field-updated value))
(defn- adjust-int [int-atom delta]
(let [v (js/parseInt @int-atom)
valid? (not (js/Number.isNaN v))
new-v (+v delta)]
(when valid?
(store-int-value int-atom new-v))))
(defn integer-field [default-value]
(let [int-atom (atom default-value)
the-int (re-frame/subscribe [:integer-field-input-value])]
(fn []
(reset! int-atom @the-int)
[:div
[:input {:type "text"
:value @int-atom
:on-change #(store-int-value int-atom(-> % .-target .-value))}]
[:button {:on-click #(adjust-int int-atom 1)} "+"]
[:button {:on-click #(adjust-int int-atom -1)}]])))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1634 次 |
| 最近记录: |