Java Script去抖的问题

问题描述

在看了 https://segmentfault.com/p/12... 关于节流,去抖的文章后,发现项目中有个位置还比较适合用debounce来解决于是决定尝试,但是去抖是ok了,发现出现个新的问题一直没想明白想请教一下;

具体就是项目中有位置显示 各种联系方式(微信,QQ,电话),当鼠标移入其中某一个时会展现对应的号码,移出后则消失,加完去抖的代码后发现只要快速在三个间移动可能会出现,最后移出的那个联系方式不会消失的问题。

相关代码

<script type="text/javascript">
    $(function() {
        $('.service_action_btn').hover(function() {
            var id_str = $(this).data('id');// #contact_qq
            debounce(showContact, $(id_str));
        }, function() {
            var id_str = $(this).data('id');// contact_qq
            debounce(hideContact, $(id_str));
        });
    });

    function debounce(method, context) {
        clearTimeout(method.tId);
        method.tId = setTimeout(function() {
            method.call(context);
        }, 500);
    }

    function showContact() {
        this.show();
    }
    function hideContact() {
        this.hide();
    }
</script>
阅读 3.4k
5 个回答

文章是我写的,我来填这个坑好了。

首先去抖逻辑用在这里没有问题,可能要实现的效果是,用户鼠标滑动很快,并不想急着改变显示状态,有一个缓冲时间。

然后,这段代码对于单个元素一点问题没有。但是,多个元素之间触发就有问题了。我试了一下,迅速划过三个button,只有最后那个button控制的文字hide了。so,为什么?

因为,hideContact是个全局变量,hideContact.tId也就是个全局变量,第一次unhover事件生成的timeId给了hideContact.tId;第二个button的unhover事件,清除hideContact.tId,会把第一个unhover事件给清除掉;同理第三个把第二个clear掉,只有第三个按钮的unhover给执行了。

当第二次调用该函数时,它会清除前一次的定时器并设置另一个

补:解决方案(参照评论),多个模块共用一个状态会出错,那么把每个模块的状态隔离开就OK了,具体代码怎么写就不详细说了。

按逻辑应该是第一个移入的不会消失呀,快速划过的话第一个的隐藏并不会触发。没搞清楚为什么是最后移入的没有消失。


比较赞同楼下的意见,移出的时候没有必要添加防抖,移除后立即清除显示的setTimeout并隐藏,视觉效果没有什么毛病。

<script type="text/javascript">
    $(function() {
        $('.service_action_btn').hover(function() {
            var id_str = $(this).data('id');
            debounce(showContact, $(id_str));
        }, function() {
            var id_str = $(this).data('id');
            clearTimeout(showContact.tId);
            hideContact.call($(id_str));
        });
    });

    function debounce(method, context) {
        clearTimeout(method.tId);
        method.tId = setTimeout(function() {
            method.call(context);
        }, 500);
    }

    function showContact() {
        this.show();
    }
    function hideContact() {
        this.hide();
    }
</script>

发现segmentfault右侧的相关标签就是类似的效果https://segmentfault.com/t/se...,且显示和隐藏都是延时的,想了想把代码改了下,隐藏不做防抖只添加延时。

<script type="text/javascript">
    $(function() {
        $('.service_action_btn').hover(function() {
            var id_str = $(this).data('id');
            debounce(showContact, $(id_str), true);
        }, function() {
            var id_str = $(this).data('id');
            debounce(hideContact, $(id_str), false);
        });
    });

    function debounce(method, context, show) {
        show ? clearTimeout(method.tId) : clearTimeout(showContact.tId);
        method.tId = setTimeout(function() {
            method.call(context);
        }, 500);
    }

    function showContact() {
        this.show();
    }
    function hideContact() {
        this.hide();
    }
</script>

hover 事件要去什么抖啊, 加了debounce 就可能会出现你现在的问题啊,因为,代码可能不被执行啊
hover 只触发一次,不是连续触发的,更本没有去抖的必要

是不是 hideContact 比 showContract 早执行了。你在两个方法里面把时间打印出来看看,有没有可能是这个问题。

你鼠标移出的时候还做什么延迟哦 鼠标移出的逻辑应该是直接清掉定时函数啊

 $(function() {
        $('.service_action_btn').hover(function() {
            var id_str = $(this).data('id');// #contact_qq
            debounce(showContact, $(id_str));
        }, function() {
            if (showConcat.tId){
               clearTimeout(showConcat.tId)
               showConcat.tId=null
            }
        });
    });
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题