AngularJS:使用$timeout在摘要循环后运行(Safari vs chrome)

AngularJS: run after digest loop with $timeout (Safari vs chrome)

本文关键字:运行 Safari vs chrome 循环 使用 timeout AngularJS      更新时间:2023-09-26

我在填写表单时编写了一些自定义验证代码,但需要将$timeout设置为>100毫秒才能使其工作,我很想知道原因。

所需的表单元素遵循此格式。如果输入错误,我会添加"novalidate"类:(注意,表单中有很多这样的元素)

<div class="dottedWrapper" ng-class="{novalidate:(newController.jobDescription.length == 0) && newController.formSubmitted}">

提交表单时,我会检查是否有任何元素具有"novalidate"类并返回。

 self.formSubmitted = true;
    $timeout(function () {
        // Validate! 
        if (document.getElementsByClassName("novalidate").length > 0) {
            return;
        }
        ... 
       }, 100); // MUST SET AT LEAST 100ms for it to work in safari

然而,只有当我在Safari中将时间设置为100毫秒以上时,这才有效。在chrome中,只需要将其设置为1ms。

如果我错了,请纠正我,但这是我的想法,并表明我是一个角度新手:

  1. 我在开头设置了"self.formSubmitted = true;"。这导致通过双向数据绑定对所有div进行更新,因为"formSubmitted"包含在ng类中。

  2. 这是通过摘要循环完成的,这意味着我不能在之后直接运行"document.getElementsByClassName("novalidate")",因为摘要循环大多只运行一次并更新所有内容。

  3. 所以。。。我使用$timeout,认为它会让当前的摘要循环运行,然后跳到下一个摘要循环。此时,应更新所有元素。

您正在打破MVC模式。不要——这是不好的做法。

你为什么不直接做:

if (self.jobDescription.length == 0 && self.formSubmitted)
    return;

除了Pixelbits的答案(我完全同意)之外,您可以尝试用以下选项之一替换$timeout;

  • $evalAsync
  • $$postDigest

前者将触发一个新的$digest循环(就像$timeout一样),而后者不会。


即便如此,我认为您最好利用内置的input验证指令。不检查DOM中是否存在novalidate类,只需检查<form>.$valid属性即可(当给定name属性时,<form>会暴露在$scope上)。

你的观点会是这样的;

<form name="myForm">
  <input ng-model="formData.jobDescription" ng-minlength="1">
</form>

然后在你的控制器中;

// var form = $scope.myForm; 
console.log(form.$valid); // true|false

现在,上面的建议可能不适用于您的用例-我们需要看到更多您的实现,以便能够在更大程度上帮助您。

相关文章: