天天看點

漫談受控與非受控元件

在大多數情況下,我們推薦使用 受控元件 來處理表單資料。在一個受控元件中,表單資料是由 react 元件來管理的。另一種替代方案是使用非受控元件,這時表單資料将交由 DOM 節點來處理。

以上是 react 官網對受控元件與非受控元件的一次解釋,大學剛剛畢業時候,看到這一段, 實在有些難以接受,在我看來,既然已經選擇使用了 React ,就應該完全徹底的使用受控元件,為什麼開發者會有直接使用 DOM 節點開發的的非受控元件。當時在 vue 中,并沒有這種設定。同時我當時在開發 Sass 網站,因為在開發 pc 端網站總是需要即時驗證(即時給予使用者互動,不讓使用者在填寫完整的資料後再提示錯誤以緻于過分沮喪)。

不過現在來看,非受控元件的确是 React 非常好的設計。

非受控的輸入就像傳統的html表單輸入一樣:

我們隻有在觸發其他事件(例如點選送出按鈕時),才可以擷取 DOM 資料中的值。

受控的輸入接受目前的值作為參數,并且在值發生改變的時候執行回調函數。

當使用者一旦進行了資料的修改,程式立刻就可以知道哪些狀态發生了改變,這時候我們就可以基于狀态修改來建構更好的表單互動與使用者體驗。

受控與非受控元件可以類比伺服器和用戶端的 push 和 pull 模型,push 是伺服器主動發送資料給用戶端,一旦有“資料改變”就立即推送,是以使用者可以基于最新的消息做處理,而 pull 模型沒法知道資料的細節變化,即使遇到了錯誤輸出也隻能間接檢查通知使用者。

如果你的表單在互動的過程中足夠簡單,僅僅隻需要送出時候驗證,并且沒有級聯資料,強制格式輸入等複雜使用者互動。那麼可以選擇非受控元件。當然選擇并不是一次性的,我們可以在開發過程中遷移非受控元件到受控元件(應該沒有小夥伴反向操作吧)。

事實上,我們在生活與開發過程中,總是會遇到類似 React 中受控與非受控元件等同的問題。其實也就是全量與增量問題。基于不同的領域,不同的設計目标,不同的使用者,不同的團隊,目前受限的資源以及當下要完成的目标設定,都會影響問題的最終決策。這裡我列出最近我遇到的幾個問題。供大家參考閱讀。

從去年開始,新項目都使用 TypeScript 進行開發,面對複雜的大型項目來說,TypeScript 利好不言而喻。尤其在業務不穩定,面臨大量改動時候。動态類型總會讓人擔驚受怕。對于老項目,我們也想從中得到 TypeScript 的利好。

前端的 vue 項目已經開發 3 年多了,目前的項目也從一個簡單的單頁面應用程式變成了基于業務的多頁面應用。同時也拆分出來一系列的基礎庫與 widget。

我們都知道修改必然是從基礎更新,目前我們還面臨着繁重的開發任務,是以我們沒有時間資源進行全量更新,同時基礎依賴中也有 Vue 業務元件。Vue 3 此時的開發進度也讓我們“進退兩難”。是以我們隻能想去改動非元件的輔助代碼。

這是我們先增加了 tsc 編譯配置,可以讓新子產品使用 TypeScript,同時可以在空閑時候修改部分老代碼。

但是,作為依賴庫,僅僅隻在内部 TypeScript 代碼是不夠的,進一步來說,老大還想要定義檔案(.d.ts)輔助其他項目開發。是以我們使用 tsc 編譯出目前代碼的所有 TypeScript 定義檔案,然後使用 gulp-insert 對定義檔案進行修改後投入使用。

面對移動端 Sass 開發,我們仍要提供複雜的表單,同時移動端不需要太多的互動。結合小程式 setData 非常耗費性能,同時小程式元件不像 Vue,React 有單向資料流的說法。是以資料放在各個元件内部反而更好,最後在送出時候,把各個元件的資料組合起來進行驗證與對比送出,無論是性能還是開發都具有更好的體驗。是以小程式表單送出反而使用“非受控元件”更好。

當然,移動端表單的側重點是減少使用者的輸入,開發的精力應該投入在表單的預設資料上,進而減少使用者的輸入操作。

在使用者創造價值的時代中,稽核使用者提供的資料一定是重中之重。而我們目前小程式可以提供分享功能。而小程式本身也有查詢文本安全的增值服務 api security.msgSecCheck。

這時候我們有兩種選擇,我們可以每一次送出可分享資料時候檢查并提示含有非法字元,這樣使用者可以清楚的知道該次的資料送出中有非法字元。當然也可以在最終分享的時候提示有非法資訊,但是此時面對如此大的資料量分享,使用者恐怕很難查詢出究竟是哪條資訊出了問題。究竟是那種方式更好?這取決于小程式的使用者量以及投入的資源。

同時還有很多例子,例如 js 檔案修改,究竟是增量(字元串級别)還是全量(單個 js 檔案) ? 大家需要根據公司和項目來判斷。是以究竟使用什麼方式,取決于你的業務,所擁有的資源,甚至是你面對的客戶量級。