記一次lodash delay引發的tooltip顯示不成功問題

需求背景

D3 tooltip內容過多,需要展示滾動條。鼠標離開定位後,立刻觸發mouseout,此時tooltip會隱藏。但是,需求是不能隱藏。那麼久從離開到隱藏之間,存在一定時間的隱藏。

用delay實現

# 全局變量控制
 cancelDealHandler(){
     if(something){ //取消
         cancle = true;
     }else {
         cancle = false;
     }
 }
 line.on('mouseover',() => {
     //觸發tooltip顯示
     showTip();
 }).on('mouseout',() => { 
    _.delay(() => {
        if(cancle){ //取消隱藏,全局變量控制
          return;
        }
        hideTip();
    },3000);
 })
 ;

上述方法實現總結

  • 確實能做到tip顯示控制
  • 不過,存在嚴重缺陷,小夥伴你知道嗎?

我們查看下delay源碼

/**
 * Invokes `func` after `wait` milliseconds. Any additional arguments are
 * provided to `func` when it's invoked.
 *
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to delay.
 * @param {number} wait The number of milliseconds to delay invocation.
 * @param {...*} [args] The arguments to invoke `func` with.
 * @returns {number} Returns the timer id.
 * @example
 *
 * delay(text => console.log(text), 1000, 'later')
 * // => Logs 'later' after one second.
 */
function delay(func, wait, ...args) {
  if (typeof func !== 'function') {
    throw new TypeError('Expected a function')
  }
  return setTimeout(func,  wait || 0, ...args)
}

export default delay

哦哦,原來,底層使用setTimeout!!!

上述方法的問題:

  • 沒調用一次delay,觸發一次setTimeout
  • 大量的mouseout,那麼久會產生很多setTimout
  • 過多的setTimout,會進入排隊等待執行,
  • 當某次代碼執行到hideTip()前,cancel= true,但是此時依舊會隱藏tip.
  • 沒有及時清空timer,雖然只會執行一次

改進

# 全局變量控制
 cancelDealHandler(){
     if(something){ //取消
         clearTimeout(delayTimer);
     }else {
         hideTip();
     }
 }
line.on('mouseover',() => {
     //觸發tooltip顯示
     clearTimeout(delayTimer);
     showTip();
 }).on('mouseout',() => { 
    clearTimeout(delayTimer);
    delayTimer = _.delay(() => {
        hideTip();
    },3000);
 })
 ;

歡迎關注我們【前端漫漫】,瞭解最新文章動態聯繫郵箱:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章