Javascript 获取可能通过角度范围的所有事件的列表$$听众人数?
在一个指令中,我试图获取给定范围可能捕获的所有事件名称的列表 观察scope对象时,我可以看到有一个Javascript 获取可能通过角度范围的所有事件的列表$$听众人数?,javascript,angularjs,angularjs-directive,angularjs-scope,dom-events,Javascript,Angularjs,Angularjs Directive,Angularjs Scope,Dom Events,在一个指令中,我试图获取给定范围可能捕获的所有事件名称的列表 观察scope对象时,我可以看到有一个$$listeners属性,它包含一个函数,还有一个$$listenersCount属性,它实际上似乎包含我定义的与给定范围相关的事件列表 我正在所显示的子作用域上侦听这些事件中的大多数,因此我假设这是一个列表,列出了“通过”给定作用域的所有事件,而不是特定作用域正在侦听的事件。不过,我不确定这些数字是什么意思 我找不到关于这些属性的任何文档,所以我假设它们是不应该用于此特定目的的内部对象 有没
$$listeners
属性,它包含一个函数,还有一个$$listenersCount
属性,它实际上似乎包含我定义的与给定范围相关的事件列表
我正在所显示的子作用域上侦听这些事件中的大多数,因此我假设这是一个列表,列出了“通过”给定作用域的所有事件,而不是特定作用域正在侦听的事件。不过,我不确定这些数字是什么意思
我找不到关于这些属性的任何文档,所以我假设它们是不应该用于此特定目的的内部对象
有没有其他方法来检索这样的列表,或者你认为它是安全的,尽管缺少文档?
让我们首先考虑使用$$侦听器。正如他在评论中引用的:
为了防止与代码发生意外的名称冲突,公共对象的名称前面加上$,私有对象的名称前面加上$$。请不要在代码中使用$或$$前缀 所以$$侦听器是angular的私有对象。它没有文档,可以在任何时候引入突破性的更改,而无需通知。而且这也不是你想要的。通过查看的代码,我们可以看到,正如您所猜测的,$$listenerCount将作用域冒泡到它的$parent,一直到root。这些数字表示有多少侦听器正在侦听一个事件。如果您正在开发一些内部工具来调试事件,那么使用$$监听器可能不受影响,但在生产站点中使用并不是最明智的做法那么,实现这一目标的书面方法是什么呢?Angular在其提供程序上提供了一个。虽然关于这方面的文档很少,但它是一个非常强大的工具。它本质上允许截取任何角度的角度,并充当中间人(在维基百科上看到更多信息)。使用这些工具,我们可以创建一个配置,在调用时捕获$1的每个实例:
.config(function ($provide) {
function wrap(oldFn, wrapFn) {
return function () {
return wrapFn.bind(this, oldFn)
.apply(this, arguments);
}
}
$provide.decorator('$rootScope', function ($delegate) {
var proto = Object.getPrototypeOf($delegate);
proto.$on = wrap(proto.$on, function ($on, name, listener) {
var deregister = $on.call(this, name, listener);
console.log(this, name, listener, deregister);
return deregister;
});
return $delegate;
});
});
每次调用$on时,我都会在这里登录。$scope是this
变量,name
和listener
是传递给$on的参数,delegister
是返回值。注意,his需要ES5,并且每次调用$on时都会增加开销
从这里,获取潜在的事件侦听器很容易。代替console.log,您可以将它们放在映射中,或者挂接到特定的映射中。你也可以把听者或听者包装起来,在每次接到电话时做额外的工作。这是一个例子
这比使用$$侦听器要好,因为$$侦听器可以在任何时间以任何方式更改$另一方面,是一个已发布的API。它将更加稳定,如果angular的changelog中没有“中断更改”通知,它将不会更改,并且是更安全的选择,即使它使用了更多异常工具。,但我想我们可以在这里找到一个非常好的答案;)。仅供参考,以
$$
开头的属性是严格私有的,不应使用(例如,BC是不保证的)。@Blackhole哈,是的,我一直在想这些属性的外观是什么,看起来很奇怪,果然是双美元“为防止与代码发生意外的名称冲突,公共对象的名称前面加上$
,私有对象的名称前面加上$$
。请不要在代码中使用$
或$
前缀。”