基於jQuery.validate及Bootstrap的tooltip開發氣泡樣式的表單校正組件思路詳解,validatetooltip
表單校正是頁面開發中非常常見的一類需求,相信每個前端開發人員都有這方面的經驗。網上有很多成熟的表單校正架構,雖然按照它們預設的設計,用起來沒有多大的問題,但是在實際工作中,表單校正有可能有比較複雜的個人化的需求,使得我們用這些外掛程式的預設機制並不能完成這些功能,所以要根據自己的需要去改造它們(畢竟自己還不到那個寫一個完美的校正架構的層次)。我用過formValidation這個校正架構,雖然它跟bootstrap配合地很好,但是校正風格太死板,不太滿足個人化的情境;後來我找到了jquery.validate,我發現這個架構還挺好的,因為它只提供校正機制,但是不提供特定校正的互動,有比較多的自訂的空間。在校正風格方面,有很多的形式,可以通過顏色,邊框,動畫,文本顯示,彈框等多種方式來產生互動,至於要用哪種,就由需求以及自己的喜好來決定了。我偏向使用氣泡提示的校正風格,因為氣泡資訊在介面上只顯示於欄位的周邊,而不會對錶單的內容有所改變,看起來體驗比較好。本文介紹自己使用jquery.validate以及bootstrap的tooltip打造一種氣泡式表單校正的思路,如果你有一些個人化較強的表單校正需求,希望這篇文章能對你有些參考價值。
線上demo(點擊下面連結頁面中的儲存按鈕,或者改變表單元素的值都能觸發校正):
http://liuyunzhuge.github.io/blog/form/dist/html/demo3.html
demo相關的邏輯代碼:
https://github.com/liuyunzhuge/blog/blob/master/form/src/js/app/demo3.js
效果預覽:
組件實現:
https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/formValidation.js
https://github.com/liuyunzhuge/blog/tree/master/form/src/js/mod/validation
(有3個關聯的檔案,可通過以上連結查看)
其它事項:
1)本文提供的校正實現依賴jquery,jquery.validate,bootstrap,並採用seajs來做模組化管理;
2)本文的demo結合之前寫的form組件來一起使用,form管理的相關文章有:
簡潔易用的表單資料設定和收集管理組件
進一步豐富和簡化表單管理的組件:form.js
相關文檔:
1)jquery.validate使用說明 : https://jqueryvalidation.org/documentation/
2)tootip使用說明: http://v3.bootcss.com/javascript/#tooltips
下面就來看看該如何?這個氣泡式的表單校正吧。
1. 實現思路
用過jquery.validate就知道,這個外掛程式預設的校正機制是在某一個表單元素校正失敗後,把校正失敗的資訊用一個label元素包裹起來,然後插入到表單元素的後面。如果我們要換成氣泡式的校正,那麼首先就要考慮把它預設的插入失敗資訊的label元素的機制給取消掉,因為有了氣泡,這個label顯然是多餘的;然後還要去修改它的校正控制邏輯,在元素校正失敗的時候,用氣泡組件顯示失敗資訊,在校正成功的時候,移除可能存在的相關的氣泡組件(因為這個元素之前如果有校正失敗的情況,就會初始化相關的氣泡組件)。至於這兩個動作該怎麼去處理,簡單的方法就是改源碼,但是改源碼會帶來更大的問題,一是不利於升級,二是不利於擴充,將來要做其它的個人化校正,就容易衝突。更好地辦法是去查閱官方文檔,找到最佳的api來做自訂,這樣的話,就能完全避免改源碼帶來的問題。如果我們碰到改造一個已有的組件來完成另一個組件,並且不得不改源碼的情況,更好的方式,不是直接把另一個組件的邏輯寫到已有的組件裡面,而是在已有的組件裡面添加合適的介面,再通過介面來完成另一個組件。
翻閱jquery.validate的文檔,可以瞭解到它最核心的api是validate這個方法,這是一個可以直接在jquery對象上調用的方法,在調用它的時候,可以通過option傳遞很多的選項,其中有兩個選項,就可以用來完成我們的自訂功能:errorPlacement與showErrors,這兩個方法的作用以及簽名分別是:
errorPlacement : function(error, element) {…}
用來自訂表格單元素失敗資訊的插入位置,如果這個方法是一個空函數,那麼失敗資訊就不會插入到DOM裡面去。它有兩個參數,error表示失敗資訊產生的jquery對象;element表示單個的表單元素的jquery對象。
showErrors: function(errorMap, errorList) {…}
用來自訂校正資訊的顯示機制。它有兩個參數,第一個參數以Object的形式,封裝了當前校正操作的所有校正失敗的資訊;第二個參數errorList是一個數組,它的每個元素包含兩個屬性element和message分別代表失敗的表單元素的jq對象和失敗資訊。另外在這個方法裡面通過this.successList還可訪問到所有校正成功的元素列表,這個successList也是一個數組,它的每個元素就是校正成功的表單元素的DOM對象。
通過前面對這兩個方法的描述,大概就能知道該如何去完成自訂的表單校正功能了:
1)如果在errorPlacement這個option裡什麼都不做,那麼校正的時候就不會插入到頁面中了;
2)在showErrors裡面,通過errorList和successList,我們可以分別遍曆一遍,給失敗的元素顯示tooltip,然後給成功的元素移除tooltip。
是簡單說明我的實現中對jquery.validate調用時的方式,只用到了前面提到的這兩個選項。
接下來就來看看實際實現時的一些要點。
2. 詳細實現
1)從程式碼群組織說起
本文實現主要包含三個檔案:
https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/formValidation.js
https://github.com/liuyunzhuge/blog/tree/master/form/src/js/mod/validation(這個檔案包含兩個檔案:validate.js和validator.js)
核心的檔案是mod/validation檔案夾下的兩個。其中:
validate.js是最核心的代碼,包含了所有的自訂邏輯; validator.js僅僅是對jquery.validate預設的校正資訊做的重設,因為它預設是英文的,而我的項目環境不需要考慮英文,所以就在這個檔案裡做了統一的處理;另外如果要添加一些全域的校正器的話,也可以考慮添加在這裡。
mod/formValidation.js是在頁面中直接引用的檔案,它依賴mod/validation/validate.js,同時基於validate.js提供的介面,註冊了一些自訂的處理,這些自訂的處理我會在後面進行說明,它的作用僅僅是為了將validate.js的功能與我之前寫的form相關組件結合起來使用。
如果你對本文的實現感興趣,但是對我寫的form相關組件不感興趣的話,完全可以考慮只關注validate.js和validator.js,因為沒有formValidation.js,它們的功能依然是完整的。
2)新添加的option
在validate.js中可以看到有一個DEFAULTS,來定義本文實現的組件模組的option,除了對jquery.validate外掛程式相關的option進行覆蓋,還增加了以下option,來完成更豐富的功能:
useTooltip: true,//配置是否啟用氣泡提示來顯示校正失敗的資訊,預設啟用tipPlacement: 'right',//全域的氣泡提示的位置tooltipDuration: 2500,//多久自動隱藏tooltipfieldConfig: {},//按欄位名稱配置一些東西,如:/** * { * title: { * fvTipTarget: function($field){ return $field.closest(...);}, //配置氣泡提示關聯的DOM元素 * tipPlacement: 'top', //配置氣泡提示的顯示位置:上下左右 * tooltipClass: 'tooltip-name', //配置氣泡提示組件需要添加的css類 * errorPlacement: function(error,element){}, //配置欄位錯誤資訊的插入位置 * fvRelatedTarget: function($field){return ...}, //配置校正時關聯影響的DOM元素 * } * } * * 其中fvTipTarget fvRelatedTarget可以是function和jQuery對象兩種形式 */fieldTypeConfig: {},//按欄位類型配置一些東西,如:/** * { * date: { * fvTipTarget: function($field){ return $field.closest(...);}, //配置date類型的欄位校正失敗時氣泡提示關聯的DOM元素 * tipPlacement: 'top', //配置date類型的欄位校正失敗時氣泡提示的顯示位置:上下左右 * tooltipClass: 'tooltip-name', //配置date類型的欄位校正失敗時氣泡提示組件需要添加的css類 * errorPlacement: function(error,element){}, //配置date類型的欄位的錯誤資訊的插入位置 * fvRelatedTarget: function($field){return ...}, //配置date類型的欄位時校正時關聯影響的DOM元素 * } * } * 如果要為所有的類型定義一個配置,可把類型名稱設定為all,如all: {errorPlacement: function(){..}} * 優先順序: * fieldConfig > fieldTypeConfig<type> > Validation.defaultFieldTypeConfig > fieldTypeConfig<all> */
詳細作用如下:
useTooltip決定了是否啟用氣泡校正的功能,預設為true,如果為false,validate.js提供的模組將使用預設的校正機制來顯示校正邏輯;
tipPlacement: 全域的氣泡提示顯示的位置,用過bootstrap的tooltip就知道,它可以顯示到一個元素的上下左右,通過這個可以改變氣泡提示的預設位置;
tooltipDuration: 配置氣泡顯示的時間。我提供的實現,在顯示氣泡時的邏輯是:在校正失敗的時候,顯示tootip,然後在這個選項指定的時間過去之後,自動消失,當滑鼠再次移入失敗元素的時候,tooltip會再次顯示,滑鼠移出的時候再消失。
fieldConfig:可以用來根據欄位名稱做一些配置,注釋中有配舉例。可配置的選項說明如下:
- fvTipTarget:用來自訂氣泡顯示在哪個元素上; - tipPlacement:配置某個元素氣泡提示的顯示位置 - tooltipClass:自訂氣泡組件的css類 - errorPlacement:自訂某個元素的失敗資訊的插入位置 - fvRelatedTarget:自訂元素校正時需要關聯影響的其它元素,其實就是在表單元素校正失敗的時候也把相關的validClass和errorClass這兩個css類,同步管理到其它元素而已。
需要注意的是,fieldConfig是根據欄位元素名稱來配置的,因為只能根據名稱來找到相應的元素,所以表單元素上面一定要有name屬性,這樣才能找到fieldConfig中的配置項。
fieldTypeConfig:可以用來按欄位類型做一些配置,它的配置項跟fieldConfig的一致,只不過它的好處在於,可以為同一個類型的欄位指定相同的配置,省的在fieldConfig裡面要重複配置。
需要注意的是:fieldType是通過在表單元素上的type屬性或者data-type屬性或者data-fv-type屬性來指定的,優先順序:data-fv-type > data-type > type。在fieldTypeConfig中,可以使用all這個特殊的type,它不需要在表單元素上指定,用來對所有的欄位進行一個統一的配置。在validate.js模組的靜態成員上,提供了defaultFieldTypeConfig對象,通過擴充這個對象,可以提供預設的一些按欄位類型的配置,方便做一些統一處理。最後一點在靜態成員部分還會再詳細介紹。
jquery.validate相關的一些需要覆蓋的option及其說明如下:
debug: true,//防止校正成功後表單自動認可submitHandler: $.noop,//屏蔽表單校正成功後的表單提交功能,由外部的Form組件負責提交ignore: '[type="hidden"]:not(.fv-yes),[disabled]:not(.fv-yes),.fv-no',//用於過濾不參與校正的元素errorElement: 'i',//使用<i>元素來包裹校正失敗的資訊errorClass: 'fv-error',//校正失敗時相應的classvalidClass: 'fv-valid'//校正成功時相應的class
需要補充的是:
a. 為啥要防止表單自動認可,因為我自己更偏向於主動控製表單提交;
b. ignore部分,沒有完全把隱藏的或者禁用的表單元素排除掉,有一些時候隱藏元素也是能夠用於校正的。
3)核心實現
核心實現的方法就是下面的代碼:
$element.validate($.extend(opts, { errorPlacement: function (error, element) { if (opts.useTooltip) { return; } //jquery.validate組件預設的校正失敗資訊的插入方式是:在該元素後面插入校正失敗的資訊 //我們可以按欄位及欄位類型通過fieldConfig與fieldTypeConfig來自訂插入的方式 var _errorPlacement = getCommonConfig('errorPlacement', element, opts); if (!isFunc(_errorPlacement)) { _errorPlacement = function () { error.insertAfter(element); } } _errorPlacement(error, element); }, showErrors: function (errorMap, errorList) { //覆蓋這個方法以便在校正失敗的時候顯示tooltip //不啟用tooltip的時候按預設的方式顯示失敗資訊 var successList = this.successList; //處理本次校正失敗的欄位 if ($.isArray(errorList)) { errorList.forEach(function (item) { setRelatedTargetStyle(item.element, opts, true); if (opts.useTooltip) { //顯示失敗的tooltip showErrorItem(item, opts, that); } }); } if ($.isArray(successList)) { successList.forEach(function (element) { setRelatedTargetStyle(element, opts, false); if (opts.useTooltip) { //移除原先可能失敗導致的tooltip showSuccessItem(element, opts, that); } }); } //官方文檔要求,在自訂showErrors之後,通過調用下面的方法完全內建的其它處理 this.defaultShowErrors(); }}));
這兩個代碼應該很好理解,因為各個部分的邏輯都已經單獨抽出來封裝了,細節可以逐一去閱讀瞭解:
以上每個方法都比較簡單,所以就不拆開來介紹了。
4)繼承jquery.validate提供的其它api方法
由於在實際的工作中,表單校正的邏輯有的時候會很複雜,尤其涉及到欄位有增刪改,校正規則有增刪改的時候,所以去看jquery.valiate的文檔,也能發現它提供了不止validate這個api,還有很多其它有用的方法,為了方便,所以直接把jquery.validate提供的其它validate.js不具備的方法都繼承過來:
//將jquery.validate的api方法代理到自身for (var i in this._validator) { if (!(i in this) && isFunc(this._validator[i])) { this[i] = (function (context, func) { return function () { return func.apply(context, arguments); } })(this._validator, this._validator[i]); }}
5)表單校正重設
一個很普遍的需求,就是有的時候需要重設表單,這個時候除了重設表單元素的值,還得重設它們的校正狀態,雖然jquery.validate有提供相關方法,但是由於我們有用到tooltip組件以及添加了一些其它處理,所以需要對錶單校正的重設功能,做一些自訂,主要是tooltip組件的銷毀和一些狀態的還原:
resetForm: function () { var $element = this.$element, opts = this.options; //清除掉tooltip組件及綁定的事件 if (opts.useTooltip) { $element.find('.fv-tip-target').each(function () { var tooltip = $(this).data('bs.tooltip'); checkHideTimeout(tooltip); tooltip && tooltip.destroy(); }).off('.fv'); } $element.find('.fv-related-target').removeClass(opts.validClass + ' fv-related-target ' + opts.errorClass); this._validator.resetForm();}
6)靜態成員
validate.js提供了一些靜態成員,有屬性也有方法,使用的方法見mod/formValidation.js。其中
defaultFieldTypeConfig:用來儲存全域的一些按欄位類型的配置項;
extendFieldTypeConfig:用來擴充defaultFieldTypeConfig。
validateEvents:用來儲存全域的一些自訂的校正事件。
addValidateEvent和removeValidateEvent用來添加和移除自訂的校正事件。
為什麼會有自訂的校正事件?因為在jquery.validate這個外掛程式的預設機制下,有些表單元素的change事件並不會觸發當前元素的校正,導致介面上不能即時反饋元素的校正狀態。這個用來協助我們自動的註冊一些元素的特殊事件,然後在這些事件回調內主動觸發對元素的校正。
3. 使用舉例
從demo相關的邏輯代碼中,就看到實際的使用舉例:
從這個舉例也能看到,新的Validation組件跟直接使用jquery.validate沒有太大的區別,就是多幾個option,rules跟messages都是jquery.validate提供的option,而fieldTypeConfig是新提供的option;但是在功能上,校正的方式已經完全變成我所期待的的氣泡式校正了,這個體驗跟jquery.validate預設的體驗比起來,肯定就要好很多了。
4. 相關CSS
為了正確顯示demo中的校正效果,css也是很重要的一部分,demo相關的css可在src/css/form.css中去尋找,跟校正相關的css可通過.fv這個關鍵詞來搜尋。
5. 總結
本文介紹了一種如何根據jquery.validate這種已有的校正架構來完成個人化的表單校正功能思路,將來在碰到其它的個人化校正需求的時候,也完全可參照這個思路,嘗試去做些統一的自訂群組件,畢竟基於已有的成果去擴充比自己去造輪子,要來的更快更輕一些。本文提供的校正方式,使用起來還是挺爽的,也支援校正規則的增刪改,方式同官方文檔,歡迎使用並討論相關的問題,我在項目中都用它,尤其在管理系統裡面開發的時候,非常高效。
以上所述希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對幫客之家網站的支援!