【问题标题】:Access Attributes / $element context from function called by Angular directive从 Angular 指令调用的函数访问属性/$element 上下文
【发布时间】:2012-10-16 04:56:26
【问题描述】:

directive definition 中,有一个用于访问$element 和$attrs 的API,因此您可以返回调用指令的元素。使用 ng-class 之类的标准指令调用自定义函数时,如何访问 $element 和 $attrs?


编辑:我知道这不是惯用的方法。这个问题适用于快速原型,这对 Angular 的许多功能都有很大的用处。只是不是关于可持续性、关注点分离等的那些。我主要关心的是速度。因此,能够使用内置指令和快速控制器方法快速完成某些事情实际上是一种美德,并且可以赢得在未来进行更全面、更正确实施的机会......


在这种情况下,我只是根据$location.path() 的值,根据this postthis one 将上下文.active 类添加到导航元素。但是,在这些示例中,您需要显式且冗余地将href 属性的内容的副本作为参数传递给您从ng-class 调用的getClass() 函数。但是没有办法以编程方式从getClass() 中访问href 属性并避免将相同的内容作为arg 重复传递吗?

例如,具有getClass() 功能的控制器可以按照我想象的方式工作:

function navCtrl($scope, $routeParams) {
    $scope.getClass = function($element, $attrs) {
        if ($location.path().substr(0, path.length) == $attrs.href) {
            return "active"
        } else {
            return ""
        }
    }
}

然后你可以简单而优雅地调用它:

<a ng-class="getClass()" href="/tasks">Tasks</a>

而不是:

<a ng-class="getClass('/tasks')" href="/tasks">Tasks</a>

(我认识到另一种选择是创建一个自定义指令来执行此操作,但现在我只想弄清楚是否可以从被调用的控制器函数中访问 $attrs 和/或 $element一个指令。谢谢!)

【问题讨论】:

    标签: javascript html angularjs


    【解决方案1】:

    你实际上可以这样做...... 但你不应该这样做。哈哈......

    这里是如何做你所要求的......

    在您的标记中,将 $event 传递给您的函数。

    <a ng-click="test($event)" href="whatever">Click Me</a>
    

    然后在你的控制器中,获取事件的目标元素:

    $scope.test = function($event) {
        alert($event.target.href);
    };
    

    现在这就是你可能不应该这样做的原因:

    如果您引用 DOM,或在控制器中操作 DOM,则会危及依赖注入以及 Angular 结构中关注点的分离。当然,如果您正在测试您的函数,您仍然可以将 $event 作为依赖项注入,但是根据您在该函数中所做的事情,您可能仍然破坏了您的 DI,并且您正在尝试让控制器执行指令工作(这是为了防止你的控制器与你的标记紧密耦合)

    也就是说,如果您所做的一切只是获得一个值,那可能没问题,但您仍然在某种程度上将控制器与您的标记耦合。如果您对该 DOM 元素执行其他任何操作,那么您就没有保留。

    【讨论】:

    • 是的,如果有事件就可以,但是在ng-class的情况下没有事件。
    • Angular 的一大优势是它适合作为快速开发框架。我从事快速原型设计业务,将在短短 3 天或长达 3 周内开发出一个应用程序。虽然我非常清楚关注点分离和依赖注入以及所有其他方面的可取性,但通常根本不值得投资于这样一个短时间的、一次性的、有限使用的项目来重构某些东西如果可以使用默认的 Angular 指令和快速控制器方法完成自定义指令。因此,我的问题。
    • 以“正确”的方式做事可能更快/同样快。学习正确的方法只是需要更长的时间。只需几行代码就可以创建一个指令来连接任何东西。在我 15 年的经验中,我继承了太多的“快速原型”、“一次性”和“有限使用”项目,而且我看到原作者被扔下车,失去了生意。结果。 Angular 中的一切都很快。一切。如果你能以“错误”的方式来做,你可以用另外两行代码以“正确”的方式来做,而且它总是值得的。即使你没有编写单元测试。
    • .. 实际上,您可能已经浪费了更多的时间试图从这个问题中得到您想要的答案,而不是仅仅以任何建议的方式实现它。
    • 一年后......我同意@blesh。自定义 Angular 指令确实是要走的路。这比您想象的要容易,而且您可以在花时间学习后立即将它们淘汰。谢谢你的好建议,@blesh!
    【解决方案2】:

    我认为你做不到。角度哲学是避免直接从控制器访问 DOM。您已经确定了在 Angular 中执行此操作的两个选项:

    • 将 href 作为参数传递,即 getClass('/tasks')
    • 或者,编写自定义指令

    或者,如果该类是纯粹的表现类并且不影响您的应用程序的运行方式,那么您可以忽略 Angular 并使用快速而肮脏的 jQuery 函数来为您完成这项工作。

    缺乏与 DOM 的直接交互一开始可能有点奇怪,但从长远来看,随着代码库的增长、变得更加复杂和需要更多测试,这是天赐之物。

    【讨论】:

    • 角度原则是避免直接从控制器访问 DOM。
    【解决方案3】:

    这是一个完全不同的答案:您不需要 Angular 来根据 href 更改样式。您可以为此使用 CSS 选择器。

    按照你的风格:

    a[href="/something"] {
        background-color: red;
    }
    

    结合你可能用 ng-class 做的任何事情应该就是你需要的一切。

    【讨论】:

    • 问题不在于如何更改样式,而在于如何更改样式取决于 Angular 路径...
    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 2017-06-18
    • 2017-07-29
    • 1970-01-01
    • 2019-11-23
    • 2012-08-08
    • 1970-01-01
    • 2016-10-26
    相关资源
    最近更新 更多