0

这是我为 AngularJS 编写的第一个指令。我想检查插入到文本输入中的图像 url 是否有效。

这就是我到目前为止所拥有的:

angular.module('directives', [])
.directive('imageUrlVerify', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ctrl) {
            var image = new Image();

            scope.$watch(function() {
                if (ctrl.$viewValue) {
                    image.src = ctrl.$viewValue;

                    if (image.complete) {
                        scope[attrs.imageValid] = true;
                    } else {
                        scope[attrs.imageValid] = false;
                    }
                } else {
                    scope[attrs.imageValid] = false;
                }
            });
        }
    }
})

我用它:

<input type="text" ng-model="imageUrl" placeholder="Image URL..." data-image-valid="imageOk" image-url-verify>

这实际上是有效的,但作为我的第一个指令,我想确保我以正确的方式做事......

我错过了什么吗?

编辑:按照@Josh-David-Miller 的回答我想出了这个:

angular.module('directives', [])
.directive('imageUrlVerify', function() {
    return {
        restrict: 'A',
        replace: true,
        scope: { url: '=', imageValid: '=' },
        template: '<input ng-model="url" placeholder="Image URL..."/>',
        link: function(scope, element, attrs) {
            var image = new Image();

            scope.$watch('url', function() {
                scope.imageValid = false;
            });

            element.on( 'blur', function() {
                image.src = scope.url;
            });

            image.onload = function() {
                scope.$apply(function() {
                    scope.imageValid = true;
                });
            };

            image.onerror = function() {
                scope.$apply(function() {
                    scope.imageValid = false;
                });
            };
        }
    }
})

并像这样使用它:

<input image-url-verify url="imageUrl" image-valid="imageOk" />

它看起来更好吗?还有什么地方可以改进?

4

1 回答 1

1

我不确定我是否遵循您的指令的目的,但可以稍微清理一下。

首先,可重用指令应该有一个隔离作用域,所以它们不能弄乱它们不应该弄乱的任何东西。在您的情况下,它实际上使代码更简单。

其次,$watch 语句没有观察任何东西。$watch 采用第一个参数,该参数是要针对当前范围进行评估的字符串表达式,或者是要与每个摘要一起执行以确定值是否更改的方法。你的方法没有返回任何东西,所以没有什么可看的。您的代码实际上只是在每个摘要上执行相同的代码。也许您可以详细说明您要在这里做什么。

最后,您的验证将在每次击键时进行,这可能不是很有帮助。我将其更改为在焦点离开输入元素时运行。

这是更新的代码:

angular.module('directives', [])
.directive('imageUrlVerify', function() {
  return {
    restrict: 'A',
    replace: true,
    scope: { url: '=', imageValid: '=' },
    template: '<input ng-bind="url" placeholder="Image URL..." valid="imageValid" />',
    link: function(scope, element, attrs) {
      var image = new Image();

      element.on( 'blur', function() {
        image.src = url;
        imageValid = url != "" && image.complete ? true : false;
      });
    }
  }
})

然后它的用法改为:

<input image-url-verify url="imageUrl" image-valid="imageOk" />

这些设计选择中的一些是偏好,一些将取决于您的具体用法,但两者都没有,这就是我将重写您的指令的方式。

于 2013-01-13T20:05:06.140 回答