前言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的驗證到這裏就基本實現了,其餘的擴展,例如:點擊提交按鈕的時候能夠跳轉到第一個錯誤組件的地方,只須要組件中經過獲取組件座標並滾動到相應的位置便可實現。
至於美觀方面,就得看美工了,文章就到這裏了,若是有錯誤或者問題的話,請你們留言,謝謝。