栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在angularJS中处理DOM:最佳做法?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在angularJS中处理DOM:最佳做法?

我认为“不要从控制器操作DOM”的口号是从过去开始的,那时指令主要/仅使用链接功能(或指令控制器只是与其他指令相互通信的一种方式)。

当前建议的最佳实践是使用“组件”(可以通过指令实现),其中基本上所有指令逻辑都保留在控制器中。(例如,请注意,在Angular
2中没有链接功能,每个组件/指令基本上都是一个类/控制器(加上一些元数据)。)

在这种情况下,我认为从 指令的* 控制器中操作 指令 模板中的DOM完全可以。 *


这个想法是让模板/ HTML保持声明性。比较以下片段:

<!--  `SomeController` reaches out in the DOM and  makes changes to `myComponent`'s template --- BAD--><div ng-controller="SomeController">  ...  <my-component></my-component>  ...</div>

<div ng-controller="SomeController">  ...  <!--    `myComponent`'s controller makes changes to    `myComponent`'s template --- OK  -->  <my-component></my-component>  ...</div>

在第一个(坏的)示例中,

myComponent
将具有不同的行为/外观,具体取决于它在DOM中出现的位置(例如,它在
SomeController
?下)。更重要的是,很难找出其他(无关)部分可能会更改其
myComponent
行为/外观。

在第二个(好的)示例中,

myComponent
的行为和外观在整个应用程序中将是一致的,并且很容易找出其含义:我只需要查看指令的定义(一个位置)。


但是有一些警告:

  1. 您不想将DOM操作代码与其他逻辑混合使用。(这将使您的代码难以维护且难以测试)。

  2. 通常,当所有子项都位于适当位置时(编译+链接),您想在链接后阶段中操作DOM。在控制器实例化期间运行DOM操作代码将意味着尚未处理模板内容。

  3. 通常,当您未在指令的上下文中实例化控制器时,您不希望运行DOM操作,因为这意味着您始终需要已编译的模板才能测试控制器。这是不希望的,因为即使您只想测试控制器逻辑中与DOM / HTML不相关的其他部分,它也会使单元测试变慢。

所以,我们能做些什么 ?

  • 在专用功能中隔离DOM操作代码。适当时将调用此函数(请参见下文),但是所有DOM交互都将集中在一个位置,这使得查看起来更加容易。

  • 将该函数公开为控制器方法,然后从指令的链接函数调用它(而不是在控制器初始化期间)。这样可以确保DOM处于所需状态(如果需要),并且还可以将“独立”控制器实例与DOM操作分离。

我们得到的是:

  • 如果将控制器实例化为指令的编译/链接的一部分,则将按预期方式调用该方法并操纵DOM。

  • 在单元测试中,如果不需要DOM操作逻辑,则可以直接实例化控制器并测试其业务逻辑(独立于任何DOM或编译)。

  • 您可以更好地控制DOM操作的发生时间(在单元测试中)。例如,您可以直接实例化控制器,但仍要传递

    $element
    ,进行您可能要进行的任何声明,然后手动调用DOM操作方法并声明元素已正确转换。
    $element
    无需添加真实的DOM,更容易传递诸如添加事件侦听器之类的模拟内容。

这种方法的缺点(公开方法,并从链接函数调用它)是多余的样板。如果您使用的是Angular
1.5.x,则可以通过使用指令控制器生命周期挂钩(例如

$onInit
$postlink
)来节省样板,而无需具有链接功能,只是为了握住控制器并在其上调用方法。(附加功能:将1.5.x组件语法与生命周期挂钩一起使用,将更易于迁移到Angular2。)

例子:

v1.5.x之前

.directive('myButton', function myButtonDirective() {  // DDO  return {    template: '<button ng-click="$ctrl.onClick()></button>',    scope: {}    bindToController: {      label: '@'    }    controllerAs: '$ctrl',    controller: function MyButtonController($element) {      // Variables - Private      var self = this;      // Functions - Public      self._setupElement = _setupElement;      self.onClick = onClick;      // Functions - Definitions      function _setupElement() {        $element.text(self.label);      }      function onClick() {        alert('*click*');      }    },    link: function myButtonPostlink(scope, elem, attrs, ctrl) {      ctrl._setupElement();    }  };})

在v1.5.x之后

.component('myButton', {  template: '<button ng-click="$ctrl.onClick()></button>',  bindings: {    label: '@'  }  controller: function MyButtonController($element) {    // Variables - Private    var self = this;    // Functions - Public    self.$postlink = $postlink;    self.onClick = onClick;    // Functions - Definitions    function $postlink() {      $element.text(self.label);    }    function onClick() {      alert('*click*');    }  }})


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/448301.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号