另一个if(!$scope.$$phase) $scope.$apply()场景-需要帮助澄清

9 浏览
0 Comments

另一个if(!$scope.$$phase) $scope.$apply()场景-需要帮助澄清

我有一个带有多个动态子表单的Angular表单。提交后,第一个表单不会被重置,而子表单会在每次提交后重置。

如果用户不重新加载页面,我们可以多次使用整个表单。

因此,在验证和提交之后,我不会重置第一个表单,而是让用户再次点击通过,并且可以添加一些额外的子表单(如果没有更改)。

只有当用户点击提交时,验证才会出现,所以作用域变量subFormSubmitted变为true,required错误仍然为true。例如:

subForm.salutation.$error.required && subFormSubmitted

在首次加载页面时 - 一切都正常。当我尝试提交子表单而没有输入任何内容时,将显示required验证。

问题是,当他第一次提交表单后,如果他不在第一个表单中更改任何内容,并且第二次进入动态表单后,只需点击提交而不输入任何内容,模型不会得到更新,也不会显示验证,尽管作用域变量具有正确的值。

当我在Web开发人员工具中检查时,变量

subForm.salutation.$error.required && subFormSubmitted

计算为true。然而,当我聚焦到输入框并输入内容时,其他输入框上的required验证立即出现。此外,当我更改第一个表单中的内容,然后进入子表单时,按下提交时,验证正确显示。

所以我想,这可能是一个应用作用域的问题。

在一些尝试和错误后,我找到了一个有效的解决方法:

我在按下提交时调用的作用域函数中添加了

if (!$scope.$$phase) {
    $scope.$digest();
}

这样可以正常工作,但经过一些研究,我发现这是一种反模式:

为什么使用if(!$scope.$$phase) $scope.$apply()是一种反模式?

所以,有人可以帮助我,并告诉我解决这个问题的“正确”方法吗?

基本上,我使用ng-show=firstFormSubmitted来控制表单的可见性。

$scope.addSubForm = function() {
            $scope.firstFormSubmitted = true;

希望你能理解我的问题,对不好的英语表示抱歉。

0
0 Comments

原因:

在Angular中,$scope.$apply和$scope.$digest是用于在异步回调中执行的(在初始的digest循环之后):例如AJAX请求、setTimeout/setInterval/setImmediate、非$q promises、DOM事件监听器等。Angular作为一个框架,在所有的异步内置操作(如$http、$timeout、指令)中自动处理这个任务。而合适的第三方扩展也会做同样的事情。

例子中,出现!$scope.$$phase && $scope.$digest()这样的代码,被认为是一个反模式的原因是,在一个良好设计的应用程序中,开发人员总是知道代码是在digest循环中执行还是不在其中,因此这个检查是多余的。而如果不在其中,则表明应用程序设计存在一些缺陷。

解决方法:

如果需要在异步回调中手动触发digest循环,可以使用$scope.$apply()方法。但是要注意,$scope.$apply()会触发整个应用程序的digest循环,这可能会导致性能问题。

在上述例子中,可以考虑删除!$scope.$$phase && $scope.$digest()这段代码,因为在良好设计的应用程序中,开发人员应该明确代码的执行环境,并且避免在非digest循环中手动触发digest循环。

在Angular中,$scope.$apply和$scope.$digest用于在异步回调中手动触发digest循环。然而,在良好设计的应用程序中,开发人员应该明确代码的执行环境,并避免在非digest循环中手动触发digest循环。因此,出现!$scope.$$phase && $scope.$digest()这样的代码被认为是一个反模式。如果需要手动触发digest循环,可以使用$scope.$apply()方法,但要注意可能引发的性能问题。

0