angular自定义验证 ngModel的一些理解

时间:2021-08-25 11:38:47

每次使用自定义校验都不记得具体详情,故而记录之

1、数据流向

初始化 ——>$formatters ——>modelValue——>用户操作——>viewValue——>$parser——>modelValue

$formatters 通过代码调用,根据return的值初始化viewValue(一般不会用上这个功能)

$parser 通过用户输入,根据return的值赋给modelValue(不返回输入值,modelValue和viewValue的值不同也是可以的,这是为了满足啥需求设计出的)

下面有个demo

 <html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>parser_uppercase</title>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module('app',[]);
app.controller('MyCtrl', function($scope){
$scope.name = 'kobe';
$scope.changeName = function(){
$scope.name = $scope.newName;
}
});
app.directive('myTag', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, ele, attrs, ctrl){
ctrl.$parsers.push(function(value){
console.log('$parsers方法被调用');
value = value.toUpperCase();
return value;
});
ctrl.$formatters.push(function(value){
console.log('$formatters方法被调用');
value = value.toUpperCase();
return value;
});
}
}
})
</script>
</head>
<body ng-controller="MyCtrl">
<input type="text" my-tag ng-model="name"/>
<Strong>ModelValue:{{name}}</Strong>
<input type="text" ng-model="newName"/>
<button ng-click="changeName()">ChangeName</button>
</body>
</html>

2、常用的校验方式($parser VS $watch)

一般有两种,一种是用$parser,一种使用$watch

 app.directive('promotionName',function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ngModelController) {
ngModelController.$parsers.push(function(viewValue) {
var reg = /^[\u4e00-\u9fa50-9A-Za-z]{1,20}$/ ;
if(!reg.test(viewValue)){
ngModelController.$setValidity("promotionName",false);
ngModelController.$formatters.push(undefined);
return undefined;
}else{
ngModelController.$setValidity("promotionName",true);
ngModelController.$formatters.push(viewValue);
return viewValue;
} })
}
};
});

使用$watch(《angularJS权威指南》demo使用watch)

app.directive('passwordConfirm',function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ngModelController) {
scope.$watch(attrs.ngModel,function (newValue,oldValue) {
if(newValue!==scope.passwordInfo.password){
ngModelController.$setValidity("passwordConfirm",false);
}else{
ngModelController.$setValidity("passwordConfirm",true);
}
})
}
};
});

$parse和$watch方式的优劣,没了解angularJS的内部源码,不能详尽分析,一句话

同步的使用$parse,涉及异步则使用$watch(我猜的)