为什么在控制器中操作DOM被认为是个坏主意?

Vik*_*don 5 javascript dom dom-manipulation angularjs angularjs-directive

许多人告诉我在控制器中操作DOM是一件非常糟糕的事情,但究竟是什么原因.它如何影响您正在制作的应用程序?这样做的最佳实践是什么?如何完成?

jor*_*ajm 7

对于大多数来自jQuery背景的开发人员,AngularJS需要一个重大的心理转变.

使用AngularJS时不进行jQuery样式DOM操作的主要原因是你的Angular应用程序不会意识到你使用jQuery对DOM做出的任何更改,因此你将无法将这些DOM元素绑定到任何模型中没有进入主要的角度h​​ackery.

至于最佳实践,我建议您使用http://codeschool.com上的全套教程来帮助您实现从"jQuery思维模式"到纯粹的Angular思维模式的跨越.

作为一个有角度的开发人员,我做过的最好的事情是完全从我的Angular项目中删除jQuery库,所以我不想回到我原来的错误方式.

但更具体地回答您的问题,有很多方法可以在Angular应用程序中向DOM添加元素.如果你想弄清楚如何做一些"Angular Way",我建议你发布一些代码和一个特定的问题.

完美的例子就像jQuery的append()和remove().这些在Angular应用程序中没有位置,因为任何由jQuery附加的元素都不会被Angular的模型看到,这使得它们对应用程序本身无用.

因此,您可能希望使用ng-repeat指令渲染DOM元素(如果有多个类似的DOM元素需要追加),并使用ng-click添加DOM元素,而不是使用jQuery追加和删除.要将数据添加到与ng-repeat指令绑定的对象,或者如果没有多个类似的元素要追加,可能只需要使用ng-show或ng-if仅在单击后呈现DOM元素.

以下是这两种方法的示例:http:
//plnkr.co/edit/4MSOoTrGGom2DpGj00x4?p = preview

<body ng-controller="MainCtrl">
    <p ng-repeat="name in names">{{name}}</p>
    <form ng-submit="addName(newName)">
      <input ng-model="newName" type="text"/>
      <button type="submit">Add Name</button>
    </form>
    <br>
    <br>
    <h1 ng-show="showHeader">Header Element</h1>
    <button ng-show="!showHeader" ng-click="showHeader = !showHeader">Show Header</button>
    <button ng-show="showHeader" ng-click="showHeader = !showHeader">Hide Header</button>
  </body>
Run Code Online (Sandbox Code Playgroud)

JS:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.names = ['Ramm', 'John', 'Keith', 'Susan', 'Janice'];

  $scope.addName = function(newName){
    $scope.names.push(newName);
  };

});
Run Code Online (Sandbox Code Playgroud)


Pan*_*kar 4

从技术上讲,控制器应该更小、更紧凑,它不应该使用 DOM。控制器只对事件调用的业务逻辑和绑定级别逻辑感兴趣。

根据我的观点,“你不应该从控制器操作 DOM ”背后的原因是,这只是因为关注点分离。如果您从控制器进行 DOM 操作,那么它会与您的控制器紧密耦合,并且该代码段无法重用。因此,通过在指令中编写该代码,相同的代码可以轻松成为可插入和可重用的组件。您可以通过放置指令标签/元素在其他地方使用相同的 DOM 操作。

查看指令定义,然后你会分析它只是为了玩 DOM,因为它在使用preLInk函数渲染它之前提供了一个对 DOM 的控制器,并且在渲染 DOM 后你可以在postLink函数中获得。

另外,指令使您可以使用指令元素,您无需对其进行编译,因为它element已经jQLite使用 Angular 中使用的 jQuery 的较小版本进行了编译。这里不需要选择器来获取指令元素 DOM。