使用 scope.$eval 将参数传递给指令回调

Pass parameter into directive callback using scope.$eval

我有一个在移动鼠标时调用的鼠标滚轮指令。但是如何在回调中传递滚动位置?

export function ngMouseWheelDown() {
    return function (scope: angular.IScope, element, attrs) {
        element.bind("DOMMouseScroll mousewheel onmousewheel",
            function (event) {

                // cross-browser wheel delta
                var event = window.event || event; // old IE support
                var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));

                if (delta < 0) {
                    scope.$apply(function () {
                        scope.$eval(attrs.ngMouseWheelDown);
                    });
                }
            });
    }
}

HTML

<div ng-mouse-wheel-up="$ctrl.scrollEvent($event)"
     ng-mouse-wheel-down="$ctrl.scrollEvent($event)"
     style="overflow-y: auto;">

您不需要评估。 AngularJs 具有绑定 - 能够评估和传递任何你想要的东西,从 parent 到 child (从控制器到指令)你只需要像这里一样创建作用域指令:

return {
    scope: {handler: '='},
    link: function ($scope, $elem, $attrs){
                 element.bind("", function(event){
                         ...
                         $scope.handler(...);
                  })
           }
}

但是正如@georgeawg 所提到的,创建一个隔离范围并不总是一个好主意,因为在一个元素中您只能有一个隔离范围。

因此,为此目的,您可以使用 $parse 服务从属性评估您的回调:

['$parse', function myDirective($parse){return {
     link: function myDirecitveLink($scope, $elem, $attrs) {
               // this is the only expression that can be evaluated whenever 
               // you need
               const handlerExpression = $parse($attrs['myHandlerName']); 

               // this is real handler you can call and pass params
               const readlHandler = handlerExpression($scope); 

               // now you can call your handler with desired params
               realHandler(...);
    }
}}]

这也会为您节省一些 CPU,因为您不会创建新的观察者,并且可以完全管理您需要评估表达式的时间和次数。

@georgeawg 感谢评论

使用$eval方法的locals参数:

export function ngMouseWheelDown() {
    return function (scope: angular.IScope, element, attrs) {
        element.bind("DOMMouseScroll mousewheel onmousewheel",
            function (event) {

                // cross-browser wheel delta
                var event = window.event || event; // old IE support
                var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));

                if (delta < 0) {
                    var locals = {$event: event, $delta: delta};
                    scope.$apply(function () {
                        scope.$eval(attrs.ngMouseWheelDown, locals);
                    });
                }
            });
    }
}

用法:

<div ng-mouse-wheel-up="$ctrl.scrollEvent($event, $delta)"
     ng-mouse-wheel-down="$ctrl.scrollEvent($event, $delta)"
     style="overflow-y: auto;">

有关详细信息,请参阅 - AngularJS scope.$eval API Reference