如何在jQuery UI Droppable放置动画完成后触发事件
问题原因
- 你之前使用
$.when的方式错误:$.when接收的是Deferred异步对象,你直接传入普通函数时,它会立即完成resolve,不会等待内部逻辑执行,所以更新逻辑还是提前触发。 drop事件触发时,拖拽的内置动画、元素归属切换的流程还未完全结束,此时直接调用总额计算方法,拿到的还是元素未完全移入新列的DOM状态。
解决方案
推荐使用以下两个方案,优先级从高到低:
方案1:利用draggable的stop事件触发更新(最稳妥)
jQuery UI的stop是拖拽全流程的最后一个回调,会等所有动画、元素移动、状态切换完全结束后触发,只需新增一个标识位标记是否成功完成drop即可:
dragUserInTable = function() { if (!$('.item').length) return; let isDropSuccess = false; // 新增drop成功标识 console.log("ok about to set up draggable and droppable"); $(".item").draggable({ addClasses: false, containment: '.workflows__table', cursor: "drabbing", snap: ".workflows__board-body", snapMode: "inner", revert: "invalid", helper: "clone", snapTolerance: 50, zIndex: 10, drag: ({ target }, elem) => { console.log('drag for '+target+ ' ' +elem); $(target).addClass('item--drag'); $(elem.helper[0]).addClass('item--dragging'); $(target).parents('.workflows__board-body').removeClass('ui-droppable-hover'); }, stop: ({ target }, elem) => { console.log('stop for '+target+ ' ' +elem); $(target).removeClass('item--drag'); $(elem.helper[0]).removeClass('item--dragging'); $(target).removeClass('item--lost'); // 拖拽完全结束后,判断是成功drop则更新总额 if (isDropSuccess) { valueUsersAndTotalValue(); isDropSuccess = false; // 重置标识 } } }); $('.workflows__board-body').droppable({ accept: '.item', tolerance: "intersect", drop: ({ target }, elem) => { console.log('drop for '+target+ ' ' +elem); $(target).find('.workflows__users').append(elem.draggable[0]); $(elem.draggable[0]).removeClass('item--drag'); $(target).find('.item--lost').removeClass('item--lost'); // 标记drop成功,待stop事件触发后再执行更新 isDropSuccess = true; }, over: ({ target }) => { console.log('over for '+target); $(target).parents('.workflows__table').find('.item--drag').addClass('item--lost').removeClass('item--drag'); } }); };
方案2:正确使用$.when等待动画完成
如果你的元素有自定义CSS过渡动画,可通过jQuery对象的promise()方法等待所有动画执行完成后再触发更新:
drop: ({ target }, elem) => { console.log('drop for '+target+ ' ' +elem); $(target).find('.workflows__users').append(elem.draggable[0]); $(elem.draggable[0]).removeClass('item--drag'); $(target).find('.item--lost').removeClass('item--lost'); // 等待拖拽元素、目标容器、拖拽辅助层的所有动画完成 $.when( $(elem.draggable[0]).promise(), $(target).promise(), $(elem.helper).promise() ).done(function() { valueUsersAndTotalValue(); }); }
内容的提问来源于stack exchange,提问作者Solvision
相关产品推荐
相关产品推荐

