Jos*_*h.F 8 clojure reagent re-frame
我有几个选择,但两者看起来都有点滞后,我认为应该有更好的选择.我只是希望能够创建表单,甚至动态创建表单(例如,从我的应用程序中向表单添加行),并具有试剂/重新框架/反应适当的访问不同输入的值.
不确定这些中的任何一个是否是最佳替代方案,因为它们都在每次运行之后运行:on-change...
选项#1 - 更新:on-change到全局原子
[:input {:value @new-job-form
:on-change #(dispatch [:new-job-form (-> % .-target .-value)])}]
(reg-event-db
:new-job-form
(fn [db [_ v]]
(assoc db :new-job-form v)))
Run Code Online (Sandbox Code Playgroud)
选项#2 - 更新一些只调度到全局原子的本地状态:on-blur
(defn text-input
"adapted from:
https://yogthos.net/posts/2016-09-25-ReagentComponents.html
The big idea is this holds local state, and pushes it to the global
state only when necessary"
[{:keys [sub-path disp]}]
(r/with-let [value (r/atom nil)
focused? (r/atom false)]
[:div
[:input
{:type :text
:on-focus #(do (reset! value @(subscribe sub-path))
(reset! focused? true))
:on-blur #(do (dispatch (conj disp @value))
(reset! focused? false))
:value (if @focused? @value @(subscribe sub-path))
:on-change #(reset! value (-> % .-target .-value))}]]))
Run Code Online (Sandbox Code Playgroud)
第二种选择稍微不那么迟钝,但比原始文本输入更加滞后......
编辑:
选项#3 - 为了完整性,与re-frame的TODOMVC相比略有不同的风格
(defn text-input
"adapted from re-frame's TODOMVC:
https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/views.cljs
note: this is one-way bound to the global atom, it doesn't subscribe to it"
[{:keys [on-save on-stop props]}]
(let [inner (r/atom "")]
(fn [] [:input (merge props
{:type "text"
:value @inner
:on-blur (on-save @inner)
:on-change #(reset! inner (-> % .-target .-value))
:on-key-down #(case (.-which %)
13 (on-save @inner) ; enter
27 (on-stop) ; esc
nil)})])))
[text-input {:on-save #(dispatch [:new-job-form {:path [:a]
:v %}])
:on-stop #(js/console.log "stopp")
:props {:placeholder "url"}}]
Run Code Online (Sandbox Code Playgroud)
重新构建,并在较低级别上reagent+ React,尝试限制对发生变化的组件的重新渲染。在您的情况下,如果除了文本字段之外另一个组件(或整个 UI)重新呈现,则可能会导致延迟,这是唯一发生变化的内容。
基于您的“选项一”的示例:
(defn busy-wait [ms]
(let [start (.getTime (js/Date.))]
(while (< (.getTime (js/Date.)) (+ start ms)))))
(defn slow-component []
(busy-wait 2000)
(.log js/console "Ouch!")
[:h2 "I was busy"])
(defn main-panel []
(let [new-job-form (re-frame/subscribe [:new-job-form])
(fn []
[:div.container-fluid
(slow-component)
[:input {:value @new-job-form
:on-change #(dispatch [:new-job-form (-> % .-target .-value)])}]
;; etc
Run Code Online (Sandbox Code Playgroud)
这会导致slow-component每次输入文本时都要重新渲染,而且确实很延迟,因为slow-component渲染至少需要 2000 毫秒。
对于上述情况,一个简单的解决方案就是提供 asslow-component函数来重新框架,将调用改为向量,即:
[:div.container-fluid
[slow-component]
Run Code Online (Sandbox Code Playgroud)
这允许 re-frame 看到slow-component不需要重新渲染,因为它的数据没有改变。当我们在原始示例中调用该函数时,我们会跳过此推理:
[:div.container-fluid
(slow-component)
Run Code Online (Sandbox Code Playgroud)
一个好的做法是在绑定到订阅时使用Form-2 组件。
| 归档时间: |
|
| 查看次数: |
1426 次 |
| 最近记录: |