【问题标题】:Better approach for triggering directive from controller从控制器触发指令的更好方法
【发布时间】:2015-10-09 13:01:43
【问题描述】:

我有一个指令需要根据控制器中服务调用的结果进行一些 DOM 操作。以下是我目前正在遵循的方法:

1) 在每个控制器范围内创建一个触发器对象,对应视图中的每个指令——在需要时进行 dom 操作

2) 创建指令并根据控制器设置的值进行 dom 操作;

app.directive("myDirective", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            attrs.$observe('myDirective', function (value) {
                if (value === "true") {
                    $(element).text("Scrolled to####" + $(element).data("scroll"));
                }

            });
        }
    };
});

3)从相应的控制器方法中将值设置为true 以触发指令功能

app.controller("controller1", ["$scope", function ($scope) {
    $scope.trigger1 = false;

    $scope.triggerDirective1 = function () {

        $scope.trigger1 = true;
    };
    $scope.trigger2 = false;

    $scope.triggerDirective2 = function () {

        $scope.trigger2 = true;
    };
}]);

<div id="c1" ng-controller="controller1">Controller 1
    <br>List 1
    <div my-directive="{{trigger1}}" data-scroll="20"></div>List 2
    <div my-directive="{{trigger2}}" data-scroll="30"></div>
    <button ng-click="triggerDirective1()">Trigger Directive 1</button>
    <button ng-click="triggerDirective2()">Trigger Directive 2</button>
</div>

完整代码在这里 - http://jsfiddle.net/qec35dq4/

我发现这种方法不太好,原因如下:

1) 附加指令的视图中会有多个元素

2) 每个指令触发器都是独立的。任何时候只有一个指令在起作用。根据视图中指令的数量,我必须跟踪相应控制器中的所有触发器。

有没有更好的方法来解决这个问题,这样就可以避免在控制器中跟踪这个触发作用域对象的依赖?我想到了使用$broadcast/$emit,$on。但也不要认为这将是一个好的解决方案。请让我知道你的想法。

提前感谢您的帮助

编辑:

新小提琴 - http://jsfiddle.net/86pk8LtL/

稍微更改了示例以更多地反映我想要实现的目标 - 页面上将有多个列表将应用此指令。基于后端的一些逻辑,需要在其中选择一些项目名单。选择项目后,应滚动列表,以便查看第一个选定项目(在示例中,我使用数据属性对滚动位置进行硬编码。但实际上指令会进行计算)。该指令的目的只是处理“滚动查看”部分,这就是为什么我对保留范围属性持怀疑态度的原因。请注意,当前的方法运行良好。只是想看看是否有更好的方法。

【问题讨论】:

  • 我看到您正在使用 msg 中传递的文本以及指令更新一些 result 元素。该触发器的文本是静态的吗?
  • 请忽略指令内的逻辑。这只是表明该指令在触发时会进行一些 DOM 操作
  • 由于在任何给定时间只有一个触发器处于活动状态,假设其他具有不同触发器的 div 不会显示是否正确?
  • 您的示例有点笨拙,如果您提供更真实的代码示例,会更容易为您提供帮助。
  • 更新了示例..所有带触发器的 div 都将始终显示..

标签: javascript angularjs angularjs-directive triggers controller


【解决方案1】:

AngularJS 并不是像事件驱动库那样使用 DOM 查询。 我建议使用控制器获取。 由于 Angular 支持 OOP 标准,尝试嵌套你的控制器,子控制器的范围是从父控制器继承的,这意味着你可以观察到哪个元素被触发的状态。看看这个基本的例子http://jsfiddle.net/qec35dq4/3/ 另外,我建议不要观察属性,而是将模型传递到指令的范围内。这将帮助您避免观察属性变化。

至少但不是最后,你并不需要关注元素的属性变化。它可以通过您的指令的attrs 获得:

app.directive("myDirective", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            attrs.$observe('myDirective', function (value) {
                if (value === "true") {
                    $("#result").text(attrs.msg);
                }

            });
        }
    };
});

编辑 这是基于您最新的 JSFiddle 的demo

【讨论】:

    【解决方案2】:

    上周我不得不做这样的事情。假设您不想编写多个指令,跨元素指令 dom 操作可能会很棘手,但是当我这样做时,我通过 ID 查找了我想要的元素。这将使您不必在范围上定义方法。

    <div id="trigger1"></div>List 2
    <div id="trigger2"></div>
    <button my-directive="trigger1" data-scroll="20">Trigger Directive 1</button>
    <button my-directive="trigger2"  data-scroll="30">Trigger Directive 2</button>
    

    还有指令。

    app.directive("myDirective", function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                    var idElem = document.getElementById(attrs.myDirective);
                    var elementToChange = angular.element(idElem);
                    element.on("click", function(){
                        elementToChange.text("Scrolled to####" + attrs.dataScroll);
                    });
                });
            }
        };
    });
    

    【讨论】:

      【解决方案3】:

      看看这个指令:https://github.com/iameugenejo/ngScrollTo 这似乎是一种非常巧妙的方式来实现你想要的。

      【讨论】:

        【解决方案4】:

        我想提两件事

        1. AngularJs 与 DOM 操作无关。

        2. 指令的工作概念,它必须完全独立于控制器和所有,必须在所有地方工作。

        在我看来,指令触发必须基于数据。

        所以在单个视图中使用多个指令如果根据数据触发就不会出现问题

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-28
          • 1970-01-01
          • 2013-01-30
          • 1970-01-01
          相关资源
          最近更新 更多