gpt4 book ai didi

javascript - Angular : What is the best way to bind to a global event in a directive

转载 作者:IT王子 更新时间:2023-10-29 02:54:02 26 4
gpt4 key购买 nike

想象一下 AngularJS 中的情况,您想要创建一个需要响应全局事件的指令。在这种情况下,假设是窗口调整大小事件。

最好的方法是什么?在我看来,我们有两个选择:1. 让每个指令绑定(bind)到事件上,并对当前元素施展魔法2. 创建一个全局事件监听器,它执行 DOM 选择器以获取应应用逻辑的每个元素。

选项 1 的优点是您已经可以访问要对其执行某些操作的元素。但是...选项 2 的优点是您不必在同一事件上多次绑定(bind)(针对每个指令),这可能会提高性能。

让我们来说明这两个选项:

选项 1:

angular.module('app').directive('myDirective', function(){

function doSomethingFancy(el){
// In here we have our operations on the element
}

return {
link: function(scope, element){
// Bind to the window resize event for each directive instance.
angular.element(window).on('resize', function(){
doSomethingFancy(element);
});
}
};
});

选项 2:

angular.module('app').directive('myDirective', function(){

function doSomethingFancy(){
var elements = document.querySelectorAll('[my-directive]');
angular.forEach(elements, function(el){
// In here we have our operations on the element
});
}

return {
link: function(scope, element){
// Maybe we have to do something in here, maybe not.
}
};

// Bind to the window resize event only once.
angular.element(window).on('resize', doSomethingFancy);
});

这两种方法都运行良好,但我觉得选项二并不是真正的“Angular-ish”。

有什么想法吗?

最佳答案

我选择了另一种方法来有效地本地化全局事件,例如调整窗口大小。它通过另一个指令将 Javascript 事件转换为 Angular 作用域事件。

app.directive('resize', function($window) {
return {
link: function(scope) {
function onResize(e) {
// Namespacing events with name of directive + event to avoid collisions
scope.$broadcast('resize::resize');
}

function cleanUp() {
angular.element($window).off('resize', onResize);
}

angular.element($window).on('resize', onResize);
scope.$on('$destroy', cleanUp);
}
}
});

在基本情况下,可以在应用程序的根元素上使用

<body ng-app="myApp" resize>...

然后在其他指令中监听事件

<div my-directive>....

编码为:

app.directive('myDirective', function() {
return {
link: function(scope, element) {
scope.$on('resize::resize', function() {
doSomethingFancy(element);
});
});
}
});

与其他方法相比,这有很多好处:

  • 对如何使用指令的确切形式不敏感。当 Angular 将以下内容视为等效时,您的选项 2 需要 my-directive:my:directivedata-my-directivex -my-directive, my_directive 可以在guide for directives中看到

  • 您只有一个地方可以准确影响 Javascript 事件如何转换为 Angular 事件,然后影响所有监听器。假设您稍后想要使用 Lodash debounce function 去抖动 javascript resize 事件.您可以将 resize 指令修改为:

    angular.element($window).on('resize', $window._.debounce(function() {
    scope.$broadcast('resize::resize');
    },500));
  • 因为它不一定会触发 $rootScope 上的事件,所以您可以通过移动放置 resize 指令

    <body ng-app="myApp">
    <div>
    <!-- No 'resize' events here -->
    </div>
    <div resize>
    <!-- 'resize' events are $broadcast here -->
    </div>
  • 您可以使用选项扩展指令,并在应用的不同部分以不同方式使用它。假设您想要在不同部分使用不同的去抖动版本:

    link: function(scope, element, attrs) {
    var wait = 0;
    attrs.$observe('resize', function(newWait) {
    wait = $window.parseInt(newWait || 0);
    });
    angular.element($window).on('resize', $window._.debounce(function() {
    scope.$broadcast('resize::resize');
    }, wait));
    }

    用作:

    <div resize>
    <!-- Undebounced 'resize' Angular events here -->
    </div>
    <div resize="500">
    <!-- 'resize' is debounced by 500 milliseconds -->
    </div>
  • 您稍后可以使用其他可能有用的事件来扩展该指令。也许像 resize::heightIncrease 这样的东西。 resize::heightDecreaseresize::widthIncreaseresize::widthDecrease。然后,您的应用程序中有一个地方负责内存和处理窗口的确切尺寸。

  • 您可以将数据与事件一起传递。比如说您可能需要处理跨浏览器问题的视口(viewport)高度/宽度(取决于您需要多远的 IE 支持,以及您是否包含另一个库来帮助您)。

    angular.element($window).on('resize', function() {
    // From http://stackoverflow.com/a/11744120/1319998
    var w = $window,
    d = $document[0],
    e = d.documentElement,
    g = d.getElementsByTagName('body')[0],
    x = w.innerWidth || e.clientWidth || g.clientWidth,
    y = w.innerHeight|| e.clientHeight|| g.clientHeight;
    scope.$broadcast('resize::resize', {
    innerWidth: x,
    innerHeight: y
    });
    });

    这让您可以在一个地方稍后添加数据。例如。假设您想发送自上次去抖事件以来的尺寸差异?您可能会添加一些代码来记住旧尺寸并发送差异。

本质上,这种设计提供了一种以可配置的方式将全局 Javascript 事件转换为本地 Angular 事件的方法,并且不仅适用于应用程序,还适用于应用程序的不同部分,具体取决于指令的位置。

关于javascript - Angular : What is the best way to bind to a global event in a directive,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23272169/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com