我正在尝试创建一个函数包装器,可以使用DOM元素作为参数进行调用,并返回一个与该DOM元素相关联的唯一去抖函数,该元素中包含一些逻辑。
我会一步一步地澄清我的思考过程:
hideElementWhenIdle = _.debounce(($el) => {
if($el.is(":hover"))
hideElementWhenIdle($el);
else
$el.removeClass("visible");
}, 5000);
现在,这个函数工作得非常好,直到我意识到我将debounced函数绑定到它调用的第一个元素。所以,如果我想创建:
hideElementWhenIdle( $("selector-1") );
hideElementWhenIdle( $("selector-2") );
他们基本上会互相辩解。我想要的是每个元素的独特功能。
当然我可以这样做:
hideElementWhenIdle = function($el) {
let fn = _.debounce(($el) => {
// ... same as above
}, 5000);
return fn;
}
hideSelector1WhenIdle = hideElementWhenIdle( $("selector-1") );
hideSelector2WhenIdle = hideElementWhenIdle( $("selector-2") );
现在我可以调用两个独立的函数。然而,这显然很脏并且不可扩展(但是,公平地说,我只需要两个元素来应用于函数)。
我以为我可以wrap
和memoize
我的功能来实现我想做的事情,但经过多次尝试后,我无法围绕正在发生的事情(或者它是否均匀)正确的解决方案)。这是我最近的尝试:
var hideElementWhenIdle = _.wrap(
_.memoize(
function($el) {
var fn = _.debounce(() => {
// ... same as above
}
),
function(func, $el) {
return func($el);
}
);
我猜我的问题是_.debounce
总是返回相同的值,所以无论$el
如何,我总是缓存相同的值。
答案 0 :(得分:1)
您的脏解决方案是我认为的方式。或者你需要自己的debouncer:
function debounce(func,time){
var debouncing=new Map();
return function(el){
if(!debouncing.get(el)){
debouncing.set(el,setTimeout(_=>debouncing.set(el,null),time));
return func(el);
}
};
}
用例:
var func=debounce(function(el){
$el=$(el);
if($el.is(":hover"))
hideElementWhenIdle($el);
else
$el.removeClass("visible");
}, 5000);
func("#sth");
func("#sth");//debounced
func("#sthelse");//not debounced
注意:这不适用于传递jquery对象,因为它们是唯一的。 DOM节点可以工作。