偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Vue3 的 watch,性能真的很差!你們知道怎么優(yōu)化嗎?

開(kāi)發(fā) 前端
如果頁(yè)面中使用了大量的 watch ,但是又沒(méi)有進(jìn)行防抖或者節(jié)流的限制,就會(huì)導(dǎo)致頁(yè)面非常卡頓。

最近發(fā)現(xiàn)公司某個(gè) Vue 頁(yè)面非常卡,一看原來(lái)是因?yàn)轫?yè)面中使用了大量的 watch ,但是又沒(méi)有進(jìn)行防抖或者節(jié)流的限制,導(dǎo)致了觸發(fā)非常頻繁,所以頁(yè)面非??D。

所以想著,想分享一下如何給 watch 加上 防抖、節(jié)流。

一、前置知識(shí):防抖與節(jié)流

在實(shí)現(xiàn)監(jiān)聽(tīng)器之前,我們需要理解兩個(gè)核心概念:

  • 防抖(Debounce): 在連續(xù)觸發(fā)時(shí),只在最后一次操作后等待指定時(shí)間執(zhí)行
  • 節(jié)流(Throttle): 在連續(xù)觸發(fā)時(shí),保證固定時(shí)間間隔內(nèi)只執(zhí)行一次

二、基礎(chǔ)監(jiān)聽(tīng)器實(shí)現(xiàn)

我們先實(shí)現(xiàn)一個(gè)簡(jiǎn)單的響應(yīng)式監(jiān)聽(tīng)器,基于Vue的watch函數(shù):

/**
 * 基礎(chǔ)監(jiān)聽(tīng)器
 * @param {Ref} source 要監(jiān)聽(tīng)的響應(yīng)式數(shù)據(jù)
 * @param {Function} callback 變化回調(diào)
 * @param {Object} options 監(jiān)聽(tīng)選項(xiàng)
 */
function basicWatcher(source, callback, options = {}) {
let cleanup = () => {}

const stop = watch(source, (value, oldValue, onCleanup) => {
    // 清除之前的副作用
    cleanup()
    
    // 注冊(cè)新的清理函數(shù)
    onCleanup(() => {
      cleanup = () => {}
    })
    
    // 執(zhí)行回調(diào)
    callback(value, oldValue)
  }, options)

return stop
}

三、實(shí)現(xiàn)防抖監(jiān)聽(tīng)器(watchDebounced)

實(shí)現(xiàn)要點(diǎn):

  • 使用 setTimeout 延遲回調(diào)執(zhí)行
  • 每次新變化時(shí)重置定時(shí)器
  • 清理函數(shù)確保組件卸載時(shí)終止等待中的回調(diào)
/**
 * 防抖監(jiān)聽(tīng)器
 * @param {Ref} source 要監(jiān)聽(tīng)的響應(yīng)式數(shù)據(jù)
 * @param {Function} callback 回調(diào)函數(shù)
 * @param {number} delay 防抖延遲時(shí)間(毫秒)
 * @param {Object} options 監(jiān)聽(tīng)選項(xiàng)
 */
function watchDebounced(source, callback, delay = 300, options = {}) {
let timeoutId = null
let cleanup = () => {}

const stop = watch(source, (value, oldValue, onCleanup) => {
    // 清除之前的定時(shí)器和副作用
    clearTimeout(timeoutId)
    cleanup()

    // 設(shè)置新的定時(shí)器
    timeoutId = setTimeout(() => {
      // 執(zhí)行回調(diào)時(shí)綁定正確的this上下文
      callback.call(this, value, oldValue)
    }, delay)

    // 注冊(cè)清理函數(shù)
    onCleanup(() => {
      clearTimeout(timeoutId)
      cleanup = () => {}
    })
  }, options)

return stop
}

四、實(shí)現(xiàn)節(jié)流監(jiān)聽(tīng)器(watchThrottled)

實(shí)現(xiàn)要點(diǎn):

  • 使用時(shí)間戳計(jì)算剩余可執(zhí)行時(shí)間
  • 未到間隔時(shí)間時(shí),設(shè)置剩余時(shí)間的定時(shí)器
  • 保證間隔時(shí)間內(nèi)至少執(zhí)行一次
/**
 * 節(jié)流監(jiān)聽(tīng)器
 * @param {Ref} source 要監(jiān)聽(tīng)的響應(yīng)式數(shù)據(jù)
 * @param {Function} callback 回調(diào)函數(shù)
 * @param {number} interval 節(jié)流間隔(毫秒)
 * @param {Object} options 監(jiān)聽(tīng)選項(xiàng)
 */
function watchThrottled(source, callback, interval = 300, options = {}) {
let lastExecTime = 0
let cleanup = () => {}
let timeoutId = null

const stop = watch(source, (value, oldValue, onCleanup) => {
    const now = Date.now()
    const elapsed = now - lastExecTime

    // 清除等待中的定時(shí)器
    clearTimeout(timeoutId)
    cleanup()

    if (elapsed >= interval) {
      // 立即執(zhí)行
      callback(value, oldValue)
      lastExecTime = now
    } else {
      // 設(shè)置剩余時(shí)間的定時(shí)器
      timeoutId = setTimeout(() => {
        callback(value, oldValue)
        lastExecTime = Date.now()
      }, interval - elapsed)
    }

    onCleanup(() => {
      clearTimeout(timeoutId)
      cleanup = () => {}
    })
  }, options)

return stop
}

五、使用示例

<script setup>
import { ref } from 'vue'

const searchKeyword = ref('')

// 防抖監(jiān)聽(tīng)示例
watchDebounced(
  searchKeyword,
  (newVal) => {
    console.log('防抖搜索:', newVal)
    // 這里可以執(zhí)行API請(qǐng)求
  },
  500
)

// 節(jié)流監(jiān)聽(tīng)示例
watchThrottled(
  searchKeyword,
  (newVal) => {
    console.log('節(jié)流記錄:', newVal)
    // 這里可以執(zhí)行高頻狀態(tài)記錄
  },
  1000
)
</script>
責(zé)任編輯:趙寧寧 來(lái)源: 前端之神
相關(guān)推薦

2025-04-07 08:50:36

2010-01-21 17:14:40

C++兼容

2013-03-20 18:14:35

架構(gòu)架構(gòu)設(shè)計(jì)項(xiàng)目

2024-07-15 08:02:37

2024-09-05 08:50:11

2020-11-12 08:32:14

Vue3模板優(yōu)化

2022-07-14 08:22:48

Computedvue3

2010-02-23 16:21:24

Python Win

2010-03-02 17:22:46

Android技術(shù)

2016-11-15 09:43:56

大數(shù)據(jù)數(shù)據(jù)工程師

2016-04-21 09:43:33

編程音樂(lè)

2022-06-09 08:28:27

Vue3watchwatchEffec

2023-12-14 08:25:14

WatchVue.js監(jiān)聽(tīng)數(shù)據(jù)

2010-03-02 15:22:40

Android手機(jī)

2025-03-10 08:48:14

Vue生態(tài)編程

2020-08-07 16:18:38

JavaScriptC++Python

2022-06-21 12:09:18

Vue差異

2010-01-20 10:14:53

C++程序

2021-08-31 10:52:30

容量背包物品

2021-01-15 05:16:37

Vue3開(kāi)源代碼量
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)