AngularJS:当用户操作同时影响模型和DOM时

AngularJS:当用户操作同时影响模型和DOM时,dom,model,angularjs,controller,directive,Dom,Model,Angularjs,Controller,Directive,这是一个AngularJS应用程序。我有一个依赖于服务的自定义指令 我真正感兴趣的是处理影响模型和DOM的用户操作的“角度方法”。一些示例代码: HTML: 当用户删除一个位置时(通过单击按钮),我还需要做一些事情来搞乱DOM,例如,将窗口滚动到顶部,等等。在控制器中有一个处理模型的函数,然后在指令中有另一个处理DOM的函数,这感觉很奇怪……但两者都基于相同的用户操作 我是不是想得太多了,还是真的错过了什么?我应该如何处理一个同时处理模型和DOM的单用户操作?当您处理AngularJS时,您可能

这是一个AngularJS应用程序。我有一个依赖于服务的自定义指令

我真正感兴趣的是处理影响模型和DOM的用户操作的“角度方法”。一些示例代码:

HTML:

当用户删除一个位置时(通过单击按钮),我还需要做一些事情来搞乱DOM,例如,将窗口滚动到顶部,等等。在控制器中有一个处理模型的函数,然后在指令中有另一个处理DOM的函数,这感觉很奇怪……但两者都基于相同的用户操作


我是不是想得太多了,还是真的错过了什么?我应该如何处理一个同时处理模型和DOM的单用户操作?

当您处理AngularJS时,您可能会听到“模型是真理的唯一来源”这句话。如果你理解了这一部分,那么剩下的事情就很容易解决了。这就是“角度的方式”

当用户交互时-他没有与DOM或视图交互。他正在与模特互动。视图本身只是模型的“视图”。同一个模型可能有其他观点——这就是为什么该模型是真理的唯一来源。现在,angular允许您在用户交互时更改模型。进行这些更改后,由于模型已更改,视图开始反映模型的更改状态

另外,为了强调关注点的分离,指令应该很少直接处理服务。指令是DOM的一部分,这意味着它是视图的一部分。服务通常与业务逻辑有关或表示模型。在MVC或MVVM中,您不会直接使视图与模型交互。始终在两者之间使用ViewModel或Controller。这将使依赖关系保持在最小值

您的ScrollToTop可以是一个从控制器调用的服务(看看哪个是Angular中的服务)。它不做你想做的,但它是一个滚动服务,这也是你需要实现你的服务的方式

编辑:

澄清一下,您通常不会在服务中操纵DOM。您可以在服务中考虑DOM操作的情况是什么时候,您想做什么不属于任何特定的HTML元素,而是需要在应用程序级别上发生的事情。 让我解释一下。例如,如果您试图在angularJS中执行诸如对话框/模式窗口之类的操作,您可能会认为,这类操作的理想位置是一个指令,因为它是一个通用的UI组件。但仔细想想,AngularJS中的指令是与元素相关联的。您总是将指令与html元素相关联。但正如我们所看到的,对话框不是附加到元素的东西,而是本质上是全局的东西。这可能是个例外

一些
$window
$document
相关内容(例如滚动)也是如此。这些不属于任何特定元素(如果您想在div中滚动,它应该是一个指令),因此它们需要是一个服务。此外,这是一个可以注入到指令中的服务。假设每次您的指令被触发时,您希望滚动到顶部或打开一个对话框。您可以将此类服务注入到指令中。您可能不应该注入指令的服务类型是与业务逻辑关联的服务。将指令视为可重用的UI组件


当然,您可以创建一个更高级别的组件(您正在尝试的东西)来创建DSL,但是您需要确切地知道您正在做什么。在此之前,我建议您坚持使用普通的旧控制器、指令和服务,并且每个控制器、指令和服务都管理自己的关注点

您可以有一个单独的指令来处理UI更改,它在您的位置集合上使用
scope.$watch
。这样,您就可以为对该集合的任何更改而通用地更新UI,只需将该指令添加到适合于您正在操作的范围的标记元素中。我用这两种方法都做过,我认为添加一个手表比在链接函数中将模型更改与jQuery或其他dom操作内容混合起来更干净。@Sounten-我不知道我是否同意按照您的建议添加$watch更干净。但我所知道的是,我对angularjs的思考超出了基本的例子,并不总是与做真实事情的最佳方式相匹配!谢谢你的意见。我会玩的。谢谢。我认为您在为我澄清关注点分离方面做得很好,尤其是您的声明“指令应该很少直接处理服务”。我有几个后续问题。如果除了滚动到顶部之外,我还想做一些其他的事情,那该怎么办?您是否建议为这些潜在的事物中的每一个创建服务?正如您可能想象的那样,我的很多问题都是由“仅在指令中进行DOM操作”驱动的。在服务中执行与DOM相关的操作是否违反了这一点?还是我现在也误解了服务关于应用程序级/全局级内容的出色澄清和解释不符合指令,并建议不要注入处理业务逻辑的服务,而是在处理对话框或文档级滚动等内容时允许。非常感谢。
<form foo-places>
    <!--other stuff -->
    <span ng-repeat="place in places">
        <button ng-click="removePlace(place)">remove {{place}}</button>
    </span>        
</form>
angular.module('foo.directives', []).directive('fooPlaces', 
function(placesService) {
    return {
        controller : function($scope) {
            $scope.places = placesService.places;
                    $scope.removePlace = function(name) {
                placesService.removePlace(name);
            };
            $scope.$on('placesChanged', function() {
                $scope.places = placesService.places;
            });
        },
        link : function($scope, element, attrs) {
                //code to do stuff when user removes a place
        }
    }
})