首页 > 解决方案 > Javascript mousup 事件触发得很晚

问题描述

我有一个jquery 排序插件,它工作得很好,但是如果我做很少的拖动操作,mouseup事件就会开始很慢。触发事件大约需要 1 秒。如果我转储 mousemove 事件的结尾,它会立即停止,但 mouseup 事件会在第二个之后开始。我为代码中的每个方法都添加了 console.log(),但在拖动停止和 mouseup 之间没有调用。可能是什么问题呢?如何在浏览器中调试可能的并行进程?代码如下所示:

    ....
        state.doc
            .on( 'mousemove', dragging )
            .on( 'mouseup', endDrag );

    }

    /**
     * @desc Start dragging
     * @param e event obj.
     */
    function dragging( e )
    {
        ...

        console.log('dragging end');
    }


    function endDrag( e )
    {
        var cEl = state.cEl,
            hintNode = $( '#sortableListsHint', state.rootEl.el ),
            hintStyle = hint[0].style,
            targetEl = null, // hintNode/placeholderNode
            isHintTarget = false, // if cEl will be placed to the hintNode
            hintWrapperNode = $( '#sortableListsHintWrapper' );

        if ( hintStyle.display == 'block' && hintNode.length && state.isAllowed )
        {
            targetEl = hintNode;
            isHintTarget = true;
        }
        else
        {
            targetEl = state.placeholderNode;
            isHintTarget = false;
        }

        offset = targetEl.offset();

        cEl.el.animate( { left: offset.left - state.cEl.mL, top: offset.top - state.cEl.mT }, 250,
            function()  // complete callback
            {
                tidyCurrEl( cEl );

                targetEl.after( cEl.el[0] );
                targetEl[0].style.display = 'none';
                hintStyle.display = 'none';
                // This has to be document node, not hint as a part of documentFragment.
                hintNode.remove();

                hintWrapperNode
                    .removeAttr( 'id' )
                    .removeClass( setting.hintWrapperClass );

                if ( hintWrapperNode.length )
                {
                    hintWrapperNode.prev( 'div' ).append( opener.clone( true ) );
                }

                var placeholderNode = state.placeholderNode;
                // Directly removed placeholder looks bad. It jumps up if the hint is below.
                if ( isHintTarget )
                {
                    placeholderNode.slideUp( 150, function()
                    {
                        var placeholderParent = placeholderNode.parent();
                        var placeholderParentLi = ( ! placeholderParent.is( state.rootEl.el ) ) ? placeholderParent.closest( 'li' ) : null;

                        placeholderNode.remove();
                        tidyEmptyLists();

                        setting.onChange( cEl.el );
                        setting.complete( cEl.el ); // Have to be here cause is necessary to remove placeholder before complete call.
                        state.isDragged = false;

                        if( setting.maxLevels !== false )  // Has to be after placeholder remove.
                        {
                            recountLevels( cEl.el );
                            if( placeholderParentLi ) recountLevels( placeholderParentLi );
                        }
                    });
                }
                else
                {
                    state.placeholderNode.remove();
                    tidyEmptyLists();
                    setting.complete( cEl.el );
                    state.isDragged = false;
                }

            } );

        scrollStop( state );

        state.doc
            .unbind( "mousemove", dragging )
            .unbind( "mouseup", endDrag );

    }

    ....

在这里https://camo.publicvm.com/我做了一个示例,其中包含代码中所有方法的转储。查看 endDragggggggggggggggggggggggggggggg 日志的延迟。我也在 Opera 浏览器中检查了这个问题,它没有问题。

编辑:我认为问题出在动画调用中的闭包中的局部变量中。var placeholderNode、var placeholderParent 和 var placeholderParentL。当我将其重写为全局状态对象时,问题就消失了。

标签: javascriptjquerygoogle-chromemouseup

解决方案


经典的用户点击触发mousedownmouseup. 两者之间的时间通常约为 50 毫秒。 在那么短的时间内,浏览器可能会因为 mousedown 和事件冒泡和传播所触发的进程而忙碌,特别是如果您在 DOM 树中绑定了太多的处理程序,例如 todocument"html, body". 避免这种情况。

此外,mouseup可能最终永远不会注册。如果某些进程花费了太多时间,或者您的鼠标速度太快,则mouseup在触发它时可能不在目标元素上方,因此永远不要触发该事件。


推荐阅读