利用jquery.validate以及bootstrap的tooltip開發氣泡式的表單校驗組件

来源:http://www.cnblogs.com/lyzg/archive/2016/07/18/5679408.html
-Advertisement-
Play Games

表單校驗是頁面開發中非常常見的一類需求,相信每個前端開發人員都有這方面的經驗。網上有很多成熟的表單校驗框架,雖然按照它們預設的設計,用起來沒有多大的問題,但是在實際工作中,表單校驗有可能有比較複雜的個性化的需求,使得我們用這些插件的預設機制並不能完成這些功能,所以要根據自己的需要去改造它們(畢竟自己 ...


表單校驗是頁面開發中非常常見的一類需求,相信每個前端開發人員都有這方面的經驗。網上有很多成熟的表單校驗框架,雖然按照它們預設的設計,用起來沒有多大的問題,但是在實際工作中,表單校驗有可能有比較複雜的個性化的需求,使得我們用這些插件的預設機制並不能完成這些功能,所以要根據自己的需要去改造它們(畢竟自己還不到那個寫一個完美的校驗框架的層次)。我用過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

效果預覽

image

組件實現

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調用時的方式,只用到了前面提到的這兩個選項。

image

接下來就來看看實際實現時的一些要點。

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,//多久自動隱藏tooltip
fieldConfig: {},//按欄位名稱配置一些東西,如:
/**
 * {
 *   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',//校驗失敗時相應的class
validClass: '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();
    }
}));

這兩個代碼應該很好理解,因為各個部分的邏輯都已經單獨抽出來封裝了,細節可以逐一去閱讀瞭解:

image

以上每個方法都比較簡單,所以就不拆開來介紹了。

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相關的邏輯代碼中,就看到實際的使用舉例:

image

image

從這個舉例也能看到,新的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這種已有的校驗框架來完成個性化的表單校驗功能思路,將來在碰到其它的個性化校驗需求的時候,也完全可參照這個思路,嘗試去做些統一的自定義組件,畢竟基於已有的成果去擴展比自己去造輪子,要來的更快更輕一些。本文提供的校驗方式,使用起來還是挺爽的,也支持校驗規則的增刪改,方式同官方文檔,歡迎使用並討論相關的問題,我在項目中都用它,尤其在管理系統裡面開發的時候,非常高效。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Ctrl+Shift+P:打開命令面板Ctrl+P:搜索項目中的文件Ctrl+G:跳轉到第幾行Ctrl+W:關閉當前打開文件Ctrl+Shift+W:關閉所有打開文件Ctrl+Shift+V:粘貼並格式化Ctrl+D:選擇單詞,重覆可增加選擇下一個相同的單詞Ctrl+L:選擇行,重覆可依次增加選擇下 ...
  • 頂求網首頁是一個web2.0博客類的網站首頁,在該網站中用戶可以發表博客,也可以推薦圖書給其他用戶。所以,在首頁中主要分三個板塊——文章、圖書、用戶。另外,網站的頭部和尾部還要有導航(navigator,固定在頭部)和腳註(footer),而這些元素也是整個網站都要用到的,具體實現時可以把它們放在網... ...
  • /*去重*/ <script> function delRepeat(arr){ var newArray=new Array(); var len=arr.length; for(var i=0;i<len;i++){ for(var j=i+1;j<len;j++) { if(arr[i]==a ...
  • [1]typeof [2]instanceof [3]toString [4]isArray ...
  • 通過jQuery獲取頁面中的所有radio對象,遍歷頁面中的radio,取消選中的標簽,因為使用到jQuery時間,因此引用到了網上公共的js,這隻是本人的一些總結,大神勿噴。 文中使用3中獲取radio對象的方式,前兩種使用的比較多,第三種直接通過type標簽獲取對象,有可能獲取到頁面中所有的ra ...
  • 1.鏈接樣式設置 設置鏈接樣式時需考慮鏈接是否已被訪問過: 2.小尖角 目前只會一種從網上搜索來的方法: 當 width:0; height:0; 時,各邊會呈現徑向三角形態,可設置各邊高、虛實、顏色,形成小尖角。 ...
  • 線上預覽 源碼下載 這是一組使用CSS3製作的超酷滑鼠滑過圖片標題動畫特效。這組特效中共有8種不同的滑鼠滑過效果,它們都是通過CSS3 transform來製作遮罩層的各種動畫特效。 使用方法 在頁面中引入imghover.css文件。 1 <link rel="stylesheet" type=" ...
  • split() 方法用於把一個字元串分割成字元串數組。<script type="text/javascript"> var str="How are you doing today?" document.write(str.split(" ") + "<br />")document.write( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...