2016-10-14 13 views
5

Tôi có một vài lựa chọn, nhưng cả hai có vẻ hơi lag, và tôi nghĩ rằng nên có một lựa chọn tốt hơn. Tôi chỉ muốn có thể tạo biểu mẫu, thậm chí tự động tạo chúng (ví dụ: thêm hàng vào biểu mẫu từ bên trong ứng dụng của tôi) và có quyền truy cập vào bộ lọc/tái khung/phản ứng thích hợp với các giá trị của các đầu vào khác nhau.Làm cách nào để xử lý các yếu tố đầu vào trong Clojure Re-Frame?

Không chắc nếu một trong hai trong số đó là phương án tốt nhất mặc dù, vì cả hai đều chạy các chức năng sau mỗi :on-change ...

Lựa chọn # 1 - cập nhật :on-change vào nguyên tử toàn cầu

[: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))) 

Tùy chọn # 2 - cập nhật một số trạng thái cục bộ, chỉ gửi đến nguyên tử toàn cầu :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))}]])) 

Lựa chọn thứ hai là hơi ít lag, nhưng nhiều lag hơn chỉ là một đầu vào văn bản thô ...

EDIT:

Lựa chọn # 3 - cho đầy đủ, một hương vị hơi khác nhau chuyển thể từ tái 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"}}] 
+0

Ý của bạn là gì? Bạn có thực sự thấy bất kỳ sự sụt giảm rõ ràng nào về hiệu suất không? Tôi đã hoàn thành rất nhiều việc sử dụng một trong hai phương pháp mà bạn mô tả và tôi chưa bao giờ gặp phải bất kỳ vấn đề hiệu suất nào. –

+0

@KubaBirecki vâng, có hiệu suất giảm rõ rệt khi hộp văn bản đấu tranh để theo kịp với cách gõ của tôi. Tôi có một máy tính nhanh, không có lý do rõ ràng nào khác tại sao nó phải chậm. –

+0

Tôi không rõ ràng chính xác yêu cầu của bạn là gì, nhưng tôi bắt đầu bằng cách xem lại khung todomvc và cách thêm todos và xem liệu bạn có bắt đầu như thế nào không: https://github.com/Day8/re -frame/tree/master/examples/todomvc –

Trả lời

0

Re-frame frame, và reagent + React trên một mức độ thấp hơn, cố gắng hạn chế tái dựng hình với các thành phần mà thay đổi. Trong trường hợp của bạn, độ trễ có thể xảy ra nếu một thành phần khác (hoặc toàn bộ giao diện người dùng) hiển thị lại ngoài trường văn bản, điều duy nhất đã thay đổi.

Một tòa nhà ví dụ trên của bạn "Lựa chọn một":

(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 

Điều này dẫn đến slow-component tái render mỗi văn bản thời gian được nhập vào, và thực sự là lag, vì slow-component mất ít nhất là 2000 ms để render.

Trong trường hợp trên, một giải pháp đơn giản là cung cấp các slow-component như một chức năng để lại khung hình, thay đổi các cuộc gọi vào một vector, ví dụ:

[:div.container-fluid 
    [slow-component] 

này cho phép tái khung để thấy rằng slow-component không cần hiển thị lại vì dữ liệu của nó không thay đổi. Chúng tôi bỏ lập luận này, khi chúng ta gọi hàm mình trong ví dụ ban đầu:

[:div.container-fluid 
    (slow-component) 

Một thực hành tốt cũng là sử dụng Form-2 components khi ràng buộc để đăng ký.

Các vấn đề liên quan