您好,我似乎无法弄清楚为什么当直接传递给 keyup 事件时,去抖动功能会按预期工作;但如果我将它包装在匿名函数中,它就不起作用。
我解决了这个问题:http://jsfiddle.net/6hg95/1/
编辑:添加了我尝试过的所有东西。
HTML
<input id='anonFunction'/>
<input id='noReturnAnonFunction'/>
<input id='exeDebouncedFunc'/>
<input id='function'/>
<div id='output'></div>
JAVASCRIPT
$(document).ready(function(){
$('#anonFunction').on('keyup', function () {
return _.debounce(debounceIt, 500, false); //Why does this differ from #function
});
$('#noReturnAnonFunction').on('keyup', function () {
_.debounce(debounceIt, 500, false); //Not being executed
});
$('#exeDebouncedFunc').on('keyup', function () {
_.debounce(debounceIt, 500, false)(); //Executing the debounced function results in wrong behaviour
});
$('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working.
});
function debounceIt(){
$('#output').append('debounced');
}
anonFunction
和 noReturnAnonFunction
不会触发去抖动功能;但最后一个 function
确实会触发。我不明白为什么会这样。有人可以帮我理解吗?
EDIT 好的,所以在#exeDebouncedFunc(你提到的那个)中没有发生去抖动的原因是因为该函数是在匿名函数的范围内执行的,另一个keyup事件将创建一个新函数在另一个匿名范围内;从而触发 debounced 函数的次数与您键入内容的次数一样多(而不是触发一次,这将是预期的行为;参见 #function
的行为)?
您能否解释一下 #anonFunction
和 #function
之间的区别。这又是一个范围问题,为什么其中一个有效而另一个无效?
编辑好的,所以现在我明白为什么会这样了。这就是为什么我需要将它包装在一个匿名函数中的原因:
小提琴:http://jsfiddle.net/6hg95/5/
HTML
<input id='anonFunction'/>
<div id='output'></div>
JAVASCRIPT
(function(){
var debounce = _.debounce(fireServerEvent, 500, false);
$('#anonFunction').on('keyup', function () {
//clear textfield
$('#output').append('clearNotifications<br/>');
debounce();
});
function fireServerEvent(){
$('#output').append('serverEvent<br/>');
}
})();
正如 Palpatim 解释的那样,原因在于 _.debounce(...)
返回一个函数,该函数在被调用时会发挥作用。
因此,在您的 #anonFunction
示例中,您有一个键侦听器,它在被调用时只向调用者返回一个函数,它对来自事件侦听器的返回值不做任何事情。
这是 _.debounce(...)
定义的片段:
_.debounce
function (func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
if (immediate && !timeout) func.apply(context, args);
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
您的关键事件侦听器必须调用 _.debounce(...)
的返回函数,或者您可以像在非匿名示例中那样做,并将 _.debounce(...)
调用的返回函数用作您的事件侦听器。
想得更轻松
_.debounce 返回一个去抖函数!因此,而不是考虑
$el.on('keyup'), function(){
_.debounce(doYourThing,500); //uh I want to debounce this
}
您宁愿调用 debounced 函数
var doYourThingDebounced = _.debounce(doYourThing, 500); //YES, this will always be debounced
$el.on('keyup', doYourThingDebounced);
keyup
上调用多个函数并且只有其中一个应该被去抖动怎么办?
$el.on('keyup', function() { doYourThingDebounced(); doYourOtherThing(); }
debounce
不执行该函数,它返回一个内置去抖动功能的函数。
Returns (Function):返回新的去抖动函数。
因此,您的 #function
处理程序实际上是在做正确的事情,方法是返回一个供 jQuery 用作 keyup 处理程序的函数。要修复您的 #noReturnAnonFunction
示例,您只需在函数的上下文中执行 debounced 函数:
$('#noReturnAnonFunction').on('keyup', function () {
_.debounce(debounceIt, 500, false)(); // Immediately executes
});
但这会在你的 debounce 周围引入一个不必要的匿名函数包装器。
您可以像这样返回 debounce 函数:
(function(){
var debounce = _.debounce(fireServerEvent, 500, false);
$('#anonFunction').on('keyup', function () {
//clear textfield
$('#output').append('clearNotifications<br/>');
return debounce();
});
function fireServerEvent(){
$('#output').append('serverEvent<br/>');
}
})();
在寻找通过尾随调用调用去抖动的解决方案时遇到了这个问题,发现这篇文章确实对我有帮助:https://newbedev.com/lodash-debounce-not-working-in-react 特别是:
对于那些因为油门/去抖不起作用而来到这里的人的解决方案 >with FunctionComponent - 您需要通过 useRef() 存储去抖函数:
export const ComponentName = (value = null) => {
const [inputValue, setInputValue] = useState(value);
const setServicesValue = value => Services.setValue(value);
const setServicesValueDebounced = useRef(_.debounce(setServicesValue, 1000));
const handleChange = ({ currentTarget: { value } }) => {
setInputValue(value);
setServicesValueDebounced.current(value);
};
return <input onChange={handleChange} value={inputValue} />;
};
Services.setValue(value);
更一般地说,如果你想要一个带有尾随行为的去抖动(考虑最后一次点击,或者更有可能是选择输入的最后一次更改),以及第一次点击/更改的视觉反馈,你将面临同样的问题。
这不起作用:
$(document).on('change', "#select", function() {
$('.ajax-loader').show();
_.debounce(processSelectChange, 1000);
});
这将是一个解决方案:
$(document).on('change', "#select", function() {
$('.ajax-loader').show();
});
$(document).on('change', "#select", _.debounce(processSelectChange, 1000));
不定期副业成功案例分享
$('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working.
是为什么 debounce 返回一个函数。像这样美丽,Just Makes Sense™