【问题标题】:How to access more than 2 DOM elements "The AngularJS way"?如何访问超过 2 个 DOM 元素“AngularJS 方式”?
【发布时间】:2015-07-03 07:43:03
【问题描述】:

我开始更好地学习 angularJS,并且我注意到 AngularJS 试图强调将视图与控制器和封装分开。一个例子是人们告诉我 DOM 操作应该放在指令中。我现在有点掌握了窍门,以及使用注入当前元素的链接函数如何实现出色的行为功能,但这并不能解释我经常遇到的问题。

示例: 我有一个要通过单击按钮打开的侧边栏。如果不使用硬编码的 javascript/jquery 选择器来抓取侧边栏,就无法在按钮的指令链接函数中执行此操作,我在 angularJS(硬编码 dom 选择器)中看到了这一点,因为它打破了关注点的分离.我想解决这个问题的一种方法是让每个元素我希望操纵一个属性指令及其链接函数,将引用它的元素属性保存到 dom-factory 中,以便每当指令需要访问自身以外的元素时,它可以调用返回元素的dom-factory,即使它不知道它来自哪里。但这是“角度方式”吗?

我这样说是因为在我当前的项目中,我正在使用硬编码的选择器,因为我一直在更改我的 css,所以维护这些选择器已经很痛苦了。必须有更好的方法来访问多个 DOM 元素。有什么想法吗?

【问题讨论】:

  • 通常可以使用范围变量(或服务)和ng-classng-show 等来执行此类操作。两者都允许使用ng-animate。在添加更多自己的 dom 操作之前考虑如何使用内置指令的数据绑定的好习惯

标签: html angularjs dom directive


【解决方案1】:

有很多方法可以解决这个问题。

一种方法是创建一个 sidebar 指令来响应“定义明确的”广播消息以打开/关闭侧边栏。

.directive("sidebar", function(){
  return {
    templateUrl: "sidebar.template.html",
    link: function(scope, element){
      scope.$root.$on("openSidebar", function(){
         // whatever you do to actually show the sidebar DOM content
         // e.x. element.show();
      });
    }
  }
});

然后,按钮可以调用某个控制器中的函数来打开侧边栏:

$scope.openSidebar = function(){
   $scope.$root.$emit("openSidebar");
}

另一种方法是使用 $sidebar 服务 - 这有点类似于 $modal 在 angularui-bootstrap 中的工作方式,但可以更简化。

【讨论】:

  • scope.$root 和 $rootScope 一样吗?我如何在控制器中使用“controller as”语法来实现你的 $scope.$root.$emit,在控制器中我通过 $scope 变量将属性绑定到“this”对象?
  • 是的,scope.$root$rootScope 的参考。从视图(controllerAs 与否)你应该能够做到ng-click="$root.$emit('openSidebar')"
【解决方案2】:

好吧,如果你在按钮上有一个指令并且你需要的元素在指令之外,你可以将你需要切换的元素的类作为属性传递

<button my-directive data-toggle-class="sidebar">open</button>

然后在你的指令中

App.directive('myDirective', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            angular.element('.' + attrs.toggleClass).toggleClass('active');
        }
    };
}

不幸的是,您不会总是让链接元素参数与您需要操作的内容相匹配。不过,有很多“角度方法”可以解决这个问题。

你甚至可以这样做:

<div ng-init="isOpen = false" class="sidebar" ng-class="{'active': isOpen}" ng-click="isOpen = !isOpen">
    ...
</div>

【讨论】:

  • Mmhh..这很好,我没有想到这一点,但不知何故,我觉得添加一个属性只会将更新重复的类/id 选择器的工作从 javascript 转移到 HTML 中。不过,它仍然比将其硬编码到指令中要好得多。如果没有更好的答案,我会记住并标记为最佳答案。另外,感谢 ng-class 解决方案,我完全忘记了这一点,你说得对,这是一种非常有角度的做法。
【解决方案3】:

指令之间最好的交流方式是通过事件。它还与关注点分离保持一致。您的按钮可以在$rootScope 上使用$broadcast,以便所有示波器都能听到。您将发出诸如sidebar.open 之类的事件。然后侧边栏指令将监听该事件并对其采取行动。

【讨论】:

  • 哦,哇,我从来没有想过,也许是因为我还没有使用 $broadcast 服务。作为一个简单的问题,我认为永远不应该使用 $rootScope,更不用说在指令中,如果我错了,请纠正我。
  • 不使用 $rootScope 背后的大部分原因是不要将所有业务价值放在那里以避免范围汤。仅使用现有范围和$broadcast$emit 可能无法将事件传递给指令,因为同级指令会错过事件。
  • 这与你永远不应该在控制器中使用$element 的论点相同。我遵循你不应该在控制器中进行 DOM 操作的口头禅,这样你就可以更轻松地测试控制器。但是,我在控制器中使用了$element 来访问定义控制器的元素上的属性并使代码更加合理,而不是在指令的链接中执行它并将新值推送到控制器中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-18
  • 2017-03-03
  • 2019-04-04
  • 2013-03-03
  • 2017-12-16
  • 1970-01-01
  • 2017-05-11
相关资源
最近更新 更多