這個表單打死我也不填!

語言: CN / TW / HK

theme: v-green highlight: atom-one-dark


本文為掘金社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!

前言

表單在應用內隨處可見,註冊、登入、完善個人資料、發表內容……在 B 端應用中,表單操作更是員工日常工作中使用最多的功能。好的表單體驗能夠讓使用者更加輕鬆地完成資訊錄入,從而讓我們獲知更多使用者的資訊、在應用內產生更多內容或者讓員工的工作更為輕鬆。糟糕的表單,則會讓使用者感到絕望,有一種打死也不想填的感覺!那麼,對於開發而言,如何提高表單操作的使用者體驗?本篇我們就來講講常見的提高表單使用者體驗的方式,推薦在封裝表單元件的時候將這些因素考慮進去,形成公司內統一的規範,保持體驗的一致性。

錯誤提示

表單輸入不可避免會出錯,及時、準確地給出錯誤提示能夠讓使用者快速更正錯誤,提高表單錄入的效率。錯誤提示有以下三種方式:

  • 內聯提示:當輸入完成後,立即校驗表單內容並給出錯誤提示;
  • 提交時客戶端提示:輸入完成後,點選提交按鈕時對整個表單進行錯誤校驗和提示;
  • 提交後服務端校驗:提交到後端後,有服務端應用對錶單進行校驗。

對於輸入表單內容較少的錯誤提示,推薦採用內聯的方式實現。內聯方式的錯誤提示就是將錯誤資訊直接顯示在表單附近(通常是下方),這樣使用者更容易察覺。我們來看看在 Flutter 中如何實現內聯的錯誤提示。 Flutter 的TextField 元件有一個 decoration屬性,型別為InputDecoration。通過 InputDecoration 類的errorTexterrorStyle可以構建一個 Text 元件,當 errorText 不為空時就會預設在 TextField 下方顯示錯誤指示,從而提示使用者輸入有誤,示例程式碼和執行結果如下。需要注意的是,錯誤提示資訊應該準確,避免泛泛的錯誤提示。我曾經遇到過的反面例子就是產品沒有明確錯誤提示(很多產品因為見過不少標準的錯誤提示,就預設開發也知道如何提示錯誤,所以文件並不會給出錯誤提示文案),然後開發直接粗暴地顯示一個“輸入有誤”的標準提示。 dart TextField( autofocus: true, decoration: InputDecoration( label: const Text('郵箱'), hintText: '請輸入電子郵箱地址', errorText: _errorText, errorStyle: TextStyle(color: Colors.red[400], fontSize: 14.0), ), onEditingComplete: () { if (!FormUtils.isValidEmail(_email)) { setState(() { _errorText = '請輸入正確的郵箱地址'; }); } else { setState(() { _errorText = null; }); } }, onChanged: (text) { _email = text; }, ) 表單校驗錯誤提示.gif 對於表單錄入內容較多的情況來說,推薦使用提交時進行錯誤校驗和提示。因為表單內容較多時,通常使用者更希望專注輸入內容,如果經常給出錯誤提示會轉移使用者注意力,打斷使用者填寫表單的思路。

標籤

表單的標籤有三種,頂部標籤、左側標籤和浮動標籤,當然簡潔的設計有時候會使用圖示替代標籤文字。研究表明,頂部標籤的方式填寫表單的效率更高,因為一路向下填寫即可,視線不需要實現 Z 字形路線移動,但是頂部標籤相對來說比較佔空間,在移動端不太多見。大多數國外的應用頂部標籤居多,例如下面是亞馬遜的登入介面。 gmail 則別出新裁地在預設的時候省去了標籤,一旦聚焦標籤顯示在輸入框的上邊框,可以說是將效率和空間做了充分的利用(這種效果在 Flutter 中預設就有,只要TextField 制定了邊框,就會在聚焦後將標籤顯示在邊框上)。 image.png

gmail.gif

在 Flutter 中,就如同我們上面的例子那樣,預設標籤是不可見的,聚焦後才會以小字的形式顯示上面的標籤。我們來看看 Flutter 文字輸入框的標籤具體如何設定。Flutter 為設定標籤樣式和互動提供了3個屬性:

  • labelStyleTextStyle 物件,用於設定預設的標籤樣式。
  • floatingLabelStyle:設定浮動狀態(即標籤在輸入框上方)時的標籤狀態,這個屬性可以是 TextStyle 物件也可以是MaterialStateTextStyle物件,如果是MaterialStateTextStyle物件的話,就可以設定不同狀態下的標籤樣式,比如錯誤、聚焦和游標移入等。
  • floatingLabelBehavior:設定浮動標籤的互動行為,預設是auto,即聚焦的時候才顯示,也可以設定為 never 不顯示標籤,或者設定為 always 一直顯示標籤。

下面是對應的程式碼,我們來看看不同形式的區別: dart Column( children: [ TextField( autofocus: true, decoration: InputDecoration( label: const Text('郵箱'), hintText: '請輸入電子郵箱地址', floatingLabelStyle: MaterialStateTextStyle.resolveWith( (Set<MaterialState> states) { final Color color; if (states.contains(MaterialState.error)) { color = Colors.red[400]!; } else if (states.contains(MaterialState.focused)) { color = Colors.blue[400]!; } else { color = Colors.black54; } return TextStyle( color: color, ); }), floatingLabelBehavior: FloatingLabelBehavior.always, errorText: _errorText, errorStyle: TextStyle(color: Colors.red[400], fontSize: 14.0), ), onEditingComplete: () { if (!FormUtils.isValidEmail(_email)) { setState(() { _errorText = '請輸入正確的郵箱地址'; }); } else { setState(() { _errorText = null; }); } }, onChanged: (text) { _email = text; }, ), TextField( decoration: InputDecoration( label: const Text('密碼'), hintText: '請輸入密碼', floatingLabelBehavior: FloatingLabelBehavior.auto, ), obscureText: true, ), TextField( decoration: InputDecoration( label: const Text('確認密碼'), hintText: '請再次輸入密碼', floatingLabelBehavior: FloatingLabelBehavior.never, ), obscureText: true, ), ], ),

  • 第一個表單郵箱我們使用了固定顯示標籤的形式,同時通過floatingLabelStyle設定了不同狀態的標籤顏色;
  • 第二個表單密碼我們使用了auto 模式,可以看到標籤一開始是在表單行內的,聚焦後標籤移到了輸入框上方,而輸入框會展示佔位文字;
  • 第三個確認密碼我們使用了never 模式,標籤一開始是在表單行內的,聚焦後標籤移到了輸入框上方,而輸入框會展示佔位文字,但標籤會消失不見。

標籤互動.gif 從體驗上來說,第一種和第二種會更好些,不過在國內大部分是直接將標籤省略或者使用左側標籤。下面是阿里雲的註冊介面,沒有標籤的表單適用於表單項較少的場景。 image.png 對於 Flutter 的 TextField,如果要使用左側標籤,則需要自定義實現(可以參考之前的文章:)。這裡需要注意,雖然 TextField 提供了一個 prefix 可以自定義前置元件,但是這個元件只會在文字框聚焦的時候才顯示。

鍵盤

鍵盤處理在手機端非常常見了,建議根據輸入型別來設定鍵盤型別,常見的鍵盤型別和用途如下:

  • TextInputType.number:輸入數字,帶小數點;
  • TextInputType.phone:輸入數字,*和#字元,適合撥打電話或輸入號碼;
  • TextInputType.email:輸入電子郵箱地址;
  • TextInputType.url:適合輸入連結地址,會預設顯示/和.字元;
  • TextInputType.multiline:適合多行輸入,帶有回車符,回車後自動換行;

需要注意的是,安卓和 iOS 的鍵盤會有些區別,具體可以看看 TextInputType 的各個列舉值的說明。

表單項過多

當要錄入的表單項很多的時候,如果表單沒有條理性,會讓使用者望而生畏,忍受力強的使用者發發鬧騷,無法忍受的使用者直接放棄。比如下面這樣的登錄檔單,看到就會絕望,打死我也不會填的image.png image.png 怎麼處理表單項過多?推薦的做法有三種:

  • 表單分組:比如將必填的表單分為一組,其他選填的表單分為一組;這種在 PC 端會更適用。
  • 分步驟填寫:還是表單分組,但是分多個步驟,每頁展示的表單數量少,不會讓使用者一下子感覺要填很多東西。而且,從心理學上來說,前面填了一部分會讓使用者積累沉沒成本,後面的表單會更願意填。同時,對於非必填的分組提供跳過選項。
  • 利用時間差:也就是一開始的時候讓使用者只填很少的資訊,然後在之後的使用過程中逐步引導使用者完善其他資料。比如在領英里,每次就會讓我們填寫一點點資訊,最終將個人資訊收集完整。

表單校驗

前面錯誤提示的時候,已經講過一些校驗的內容了。這裡要說的是,我們開發一定要養成對錶單進行校驗的習慣。本人就遇到過這樣的情況,產品沒有特別說明校驗規則,然後前後端都不校驗,結果錄入的資料導致各種各樣的 bug。這種寫 bug 的行為會極大降低我們程式設計師的段位!對於校驗,建議是在內部形成統一的預設規則,比如下面幾點:

  • 文字輸入的最大輸入長度限制;
  • 數值的最大輸入範圍;
  • 小數預設保留的位數;
  • 常用型別資料的校驗規則統一,例如姓名、郵箱、手機號、身份證號、經緯度、日期、企業統一社會信用程式碼,密碼強度、金額等。避免前後端校驗規則不一致。

至於什麼時候校驗,建議是按表單數量來定,表單數量少可以在輸入完成後進行校驗;表單數量多推薦是在完成輸入後整體校驗。同時,前端務必保證提交給後端資料的基本合法性(除了需要後端通過業務邏輯校驗的除外,例如唯一性檢查,是否存在檢查等)。

總結

如果評估一個前端開發做事情的細緻程度,通常會通過他寫的表單業務來評估。基本上,測試一遍表單的輸入互動、錯誤驗證就能夠判斷出來。一個好的前端,即便是產品不說,也會按照規範將互動和基本的校驗做好。同時,保持與產品的溝通也很重要,如果對錶單的校驗規則有疑惑,那一定是需要二次確認的。雖然不確認鍋可以甩給產品,但是 bug 卻是留在自己頭上的。