【问题标题】:AngularJS: When user action impacts both the model and the DOMAngularJS:当用户操作同时影响模型和 DOM 时
【发布时间】:2013-05-08 01:45:03
【问题描述】:

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

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

HTML:

<form foo-places>
    <!--other stuff -->
    <span ng-repeat="place in places">
        <button ng-click="removePlace(place)">remove {{place}}</button>
    </span>        
</form>

JS:

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
        }
    }
})

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

我是在想这件事还是真的错过了什么?我应该如何处理同时处理模型和 DOM 的单个用户操作?

【问题讨论】:

  • 您可以有一个单独的指令来处理在您的地点集合上使用 scope.$watch 的 UI 更改。这样,您可以针对该集合的任何更改普遍更新 UI,只需将该指令添加到适合您正在操作的范围的标记元素。我已经这样做了两种方式,我认为添加手表比混合更干净使用链接函数中的 jQuery 或其他 dom 操作内容更改模型。
  • @Sounten - 我不知道我是否同意按照您的建议添加 $watch 更清洁。但我所知道的是,除了基本示例之外,我对 angularjs 的看法并不总是与做真实事情的最佳方式相匹配!感谢您的输入。我会玩这个。

标签: dom model angularjs controller directive


【解决方案1】:

在处理 AngularJS 时,您可能听说过“模型是事实的单一来源”这句话。如果你理解了这部分,那么剩下的事情就很容易到位了。这就是“Angular 方式”。

当用户交互时 - 他没有与 DOM 或视图交互。他正在与模型互动。视图本身只是模型的“视图”。同一模型可能有其他视图——这就是为什么该模型是唯一的事实来源。现在,Angular 允许您做的是在用户交互时对模型进行更改。您进行了这些更改,并且由于模型已更改,因此视图开始反映模型的更改状态。

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

您的 ScrollToTop 可能是您从控制器调用的服务(查看 $anchorScroll,它是 Angular 中的服务)。它不会做你想做的事,但它是一个滚动服务,这也是你需要实现的。

编辑:

为了澄清,您通常不会在服务中进行 DOM 操作。您可以在服务中考虑 DOM 操作的场景是,您尝试做的事情不属于任何特定的 html 元素,而是需要在您的应用程序级别发生的事情。

让我解释一下。例如,如果你试图做一个对话框/模态窗口之类的事情——在 angularJS 中,你会认为,这样的事情的理想位置是指令,因为它是一个通用的 UI 组件。但是如果你仔细想想,AngularJS 中的指令就是与元素相关联的东西。您总是将指令与 html 元素相关联。但正如我们所见,对话框不是附加到元素上的东西,而是本质上是全局的东西。这大概是个例外。

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

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

【讨论】:

  • 谢谢。我认为您为我澄清了关注点分离的工作做得很好——尤其是您的声明“指令应该很少直接处理服务”。我有几个后续问题。如果我想做除了滚动到顶部之外的“DOM-manipulating-ish”的其他事情怎么办?你会建议为这些潜在事物中的每一个创建服务吗?正如您可能想象的那样,我的很多问题都是由“仅在指令中进行 DOM 操作”驱动的。在服务中做与 DOM 相关的事情是否违反了这一点?还是我现在也误解了服务? :)
  • 对不适合指令的应用程序级/全局内容进行了出色的澄清和解释,以及建议不要注入处理业务逻辑的服务,而是在处理内容时允许它像对话框或文档级滚动。非常感谢。
猜你喜欢
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 2023-04-03
  • 2010-10-07
  • 1970-01-01
相关资源
最近更新 更多