項目演化系列--驗證體系(基於angular的前端驗證)

前言html

  以前分享的《web項目演化--驗證體系》中提到基於angular的驗證,可是爲了以防讀者迷惑,可以好的理解驗證體系,因此沒有詳細介紹。前端

  今天特意補寫一篇關於構建angular的驗證。web

  前端驗證組件雖然對於美工的要求會更多,可是真實的應用環境下,其實對業務的要求會更高,須要組件有統一的規範,除非設計通用組件,不然應該更關注業務來進行設計。ajax

  有了統一的驗證組件,複合組件能夠重用單一的文本框、輸入框、複選框等組件,開發人員能夠節省很多時間,而且在後期須要對網站風格統一調整的時候,只須要改變相應的組件便可完成變動。app

實現異步

  首先須要定義一個驗證的規則,須要包含驗證的方式、驗證參數,好比:['stringLength', { min: 1, max: 6 }],這是我當前使用的驗證體系的規則,因爲anuglar的便利性,咱們能夠直接使用一個屬性來存儲該值。網站

  有了規則,就須要一個驗證的類來驗證以上定義的規則,大體代碼以下:ui

demo.factory('$validator', [
	function () {
	    return {
	        stringLength: function (opts, value, callback) {
	            if (typeof value !== 'string' && value != null)
	                value = value.toString();

	            var min = opts.min || 0;
	            var max = opts.max || 0;
	            callback(value ? (max == 0 ? value.length >= min : value.length >= min && value.length <= max) : min === 0);
	        }
	    };
	}
]);

  驗證方法中之因此使用異步回掉方式,是爲ajax驗證方式預留的。this

  有了驗證類,只要在組件中進行相應的引用,而後獲取存有驗證規則的屬性,並用驗證類進行驗證便可,代碼以下:spa

demo.directive('ucInput', [
	'$validator',
	function ($validator) {
	    return {
	        replace: true,
	        scope: {
	            data: '='
	        },
	        template: '<input ng-style="{ \'background-color\': isValid && \'white\' || \'red\' }" type="text" ng-model="data" />',
	        link: function (scope, el, attrs) {
	            scope.isValid = true;

	            var validType = scope.$parent.$eval(attrs.validType);
	            el.bind('blur', function () {
	                var fn = function () {
	                    scope.isValid = $validator[validType[0]](validType[1], scope.data);
	                };
	                var phase = scope.$root.$$phase;
	                if (phase == '$apply' || phase == '$digest') {
	                    if (fn && (typeof (fn) === 'function'))
	                        fn();
	                }
	                else {
	                    scope.$apply(fn);
	                }
	            });
	        }
	    };
	}
]);

  組件的效果比較醜,別在乎細節(^_^),當用戶焦點離開組件的時候,組件就會進行驗證,所以該組件就須要用戶的主動操做纔能有效果了。

  然而若是用戶不操做組件,直接點擊提交按鈕那該怎麼辦呢?

  因而乎就須要一個容器指令,來包裹全部的驗證組件,並在觸發提交按鈕的時候,也可讓包含在內的全部驗證組件本身觸發驗證。

  咱們不可能在每個驗證組件中都寫一堆類似的驗證代碼來實現驗證,並且業務中,若是組件移除或者隱藏都應該將組件排除到驗證列表外,所以就須要一個額外的類來承擔這個責任,代碼以下:

demo.directive('ucForm', [
	function () {
	    return {
	        require: 'ucForm',
	        controller: [
				function () {
				    this.controls = [];
				}
	        ],
	        link: function (scope, _, attrs, formCtrl) {
	            scope.onSubmit = function (callback) {
	                var ep = new EventProxy();
	                ep.after('valid', formCtrl.controls.length, function (res) {
	                    var b = true;
	                    for (var i = 0; i < res.length; i++) {
	                        b = res[i];
	                        if (!b)
	                            break;
	                    }
	                    if (b)
	                        callback();
	                });

	                for (var i = 0; i < formCtrl.controls.length; i++) {
	                    formCtrl.controls[i].valid(function (b) {
	                        ep.emit('valid', b);
	                    });
	                }
	            };
	        }
	    };
	}
]);

demo.factory('$valid-ui', [
	'$validator',
	function ($validator) {
		function Control(validType, property) {
		    this.validType = validType;
		    this.disable = false;
		    this.isValid = true;
		    this.property = property;
		    this.value = '';
		}

		Control.prototype.valid = function (callback) {
		    this.isValid = true;
		    if (this.disable && callback)
		        return callback(true);

		    var self = this;
		    $validator[this.validType[0]](this.validType[1], self.value, function (b) {
		        if (callback)
		            callback(b);

		        self.isValid = b;
		    });
		};

		return {
		    create: function (validType, property) {
		        return new Control(validType, property);
		    }
		};
	}
]);

  有了以上的支持,接下來只須要修改一個ucInput,而且將ucForm.onSubmit綁定到提交按鈕上即可以實現一鍵驗證的效果了,具體的實現代碼這裏就不提供了。

結束語

  那麼基於angular的驗證到這裏就基本實現了,其餘的擴展,例如:點擊提交按鈕的時候能夠跳轉到第一個錯誤組件的地方,只須要組件中經過獲取組件座標並滾動到相應的位置便可實現。

  至於美觀方面,就得看美工了,文章就到這裏了,若是有錯誤或者問題的話,請你們留言,謝謝。

相關文章
相關標籤/搜索