javascript - 在我的函数中有一个 jQuery 动画。我想仅在动画完成后从函数中返回。如何?

标签 javascript jquery

考虑这个函数:

function hideElements( selector ) {
    var number = $( selector ).length;
    if ( number ) {
        $( selector ).animate( { opacity: 0 }, 1000, function() {
            *RETURN* number + " elements are now completely hidden.';
        } );
    } else return "No matching elements found";
}

var returnedMessage = hideElements( ".hideable-divs" );

大写的RETURN是回调的返回值,所以它不起作用;我只是把它放在那里来传达这个想法。如何才能使 hideElement 函数仅在动画完成后返回某些内容?是的,任何需要 returnedMessage 变量的代码都必须等待(同步(?))直到动画完成。谢谢!

** 编辑 ** 这不是一个重复的问题,而是我正在处理的一个非常具体的场景:

第三方脚本使用确认对话框询问用户是否确定要删除 div。如果用户单击“确定”,该元素会立即从 DOM 中删除。

我的目标是:

  1. 绕过确认对话框,这样用户就不必进行确认。
  2. 以动画方式删除操作,以便用户清楚地看到删除操作的发生,并在用户意外点击时根据需要撤消操作。

为此,我重新声明了 window.confirm,如下面的代码示例所示。 (为了消除任何混淆,请注意,此更新改变了我原来的问题和我上面发布的代码块背后的想法。)

var clickTarget;
$( document ).on( 'mousedown', function( event ) {
    clickTarget = event.target;
} );
window.confirm = function( message ) {
    if ( message.indexOf( 'OK to delete' ) !== -1 ) {
        var $element = $( clickTarget ).parent();
        $element.animate( { height: 0 }, 1000, 'swing', function() {} );
        return true; // the 3rd party script receives this confirmation asynchronously and removes $element before it has a chance to be animated.
    } else return confirm( message );
};

目前,我通过创建克隆并为其设置动画而不是要删除的实际元素来实现效果。但这相当“肮脏”,我想知道是否有一种“更干净”的方法来做到这一点。谢谢!

最佳答案

正如 Weedoze 提供的链接中所建议的,通常您不想阻止异步代码上的脚本,而是提供回调。

与上述链接的主要区别在于您想要等到所有动画完成,而不是在每个元素的动画完成时调用它。在 JQuery 中,您可以使用 .promise().done() 来做到这一点:

function hideElements( selector, callBack ) {
    var sel = $( selector );
    if ( sel.length) {
        sel.animate( { opacity: 0 }, 1000).promise().done(function(){
           callBack(sel.length + " elements are now completely hidden.");
        });
    } else 
    	callBack("No matching elements found");
}

hideElements('div', console.log);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>a</div>
<div>b</div>
<div>c</div>

另一种方法是让您的 hideElements 函数本身返回一个 Promise (如果没有找到元素,则返回已解决的 Promise):

function hideElements( selector ) {
    var sel = $( selector );
    if ( sel.length) {
    	return sel.fadeOut(1000).promise().then(function(){
        	return sel.length + " elements are now completely hidden.";
        });
    } else 
    		return Promise.resolve(("No matching elements found"));
}

hideElements('div').then(console.log);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>a</div>
<div>b</div>
<div>c</div>

<小时/>

编辑

根据添加的信息:让第 3 方代码等待有点棘手。您可以让您自己的代码等待(例如使用异步等待),但根据定义,调用代码应该继续(不阻塞用户界面)。 您可以做的是取消第一次单击时的删除(返回 false),但记住调用代码的元素。然后在回调中,调用同一元素上的单击以重新启动第 3 方代码,这次返回 true 以让删除继续进行:

let clickTarget, curDelete;
$( document ).on( 'mousedown', function( event ) {
    clickTarget = event.target;
} );

let defConfirm = window.confirm; //needed to store the default functionality to avoid recursion in the call below
window.confirm = function(message) {	
    if ( message.indexOf( 'OK to delete' ) !== -1 ) {		
		if(clickTarget === curDelete)return true; //the confirm is called from the current delete, invoked by the click from the callback, return true		
        var $element = $( clickTarget ).parent(); //layout based on your example
        $element.slideUp(2000, function(){ //used slide up, but the callback can be used for any animation
			curDelete = clickTarget; //NB: perhaps an extra check is needed to see if another delete isn't started?
			$(curDelete).click(); //invoke 3rd party script by emulating click (preferably, if a method is known it is called directly)
		});		
        return false; //this result is returned before the animation finishes to stop the direct deletion
    } else return defConfirm( message ); //show default confirm window
};


//3rd party spoof
$('div > div').click(function(){
	if(confirm('dsaf asfda OK to delete aadf?'))
		console.log('3rd Party delete executing');		
});
div > div{
  width:100px;
  border: 1px solid gray;
  margin: 2px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div id=a>click me</div>
<div id=a>or me</div>
<div id=a>or me</div>
</div>

关于javascript - 在我的函数中有一个 jQuery 动画。我想仅在动画完成后从函数中返回。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48496715/

相关文章:

javascript - 将 JavaScript 转换为 Python 代码时出现十六进制问题

javascript - 函数声明 - 函数表达式 - 作用域

javascript - 使用 DOM 来识别序列中的数字

jquery - 无法让光谱颜色选择器工作

javascript - 展开搜索栏 onclick

javascript - 将 PHP 变量传递到 Jquery 弹出窗口

javascript - 通过存储的数据获取 jQuery 元素

javascript - 在浏览器后面打开窗口

javascript - AngularJS新推()'ed item to ngRepeat $Scope doesn' t有效编辑或删除

javascript - GridStack JS 设置网格框的顺序