欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3指令之搜索框輸入防抖功能實(shí)現(xiàn)

 更新時(shí)間:2022年12月29日 11:20:54   作者:Lvzl  
在Vue開發(fā)中遇到了搜索框輸入防抖處理,算是防抖的使用場景之一吧,這篇文章主要給大家介紹了關(guān)于Vue3指令之搜索框輸入防抖功能實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下

前言

「搜索??」這個(gè)場景在各種業(yè)務(wù)的系統(tǒng)中都是是非常常見的,比如電商平臺的商品搜索、百度搜索、掘金搜索、google搜索......,只要是有內(nèi)容呈現(xiàn)給用戶的,都少不了搜索功能。

按照觸發(fā)搜索動作的不同可分為:

  • 輸完關(guān)鍵字后手動觸發(fā)搜索
  • 輸入字符自動搜索

第一種是由用戶去決定何時(shí)進(jìn)行搜索,沒啥問題。

第二種是通過監(jiān)聽用戶錄入的事件自動搜索,自動搜索能在一定程度上提升用戶體驗(yàn)(比如在用戶輸入時(shí)關(guān)鍵詞聯(lián)想提示),同時(shí)也可能會帶來問題,因?yàn)?code>input事件觸發(fā)是非常頻繁的,比如下面這個(gè)示例:

打開百度的搜索,找到輸入框的dom,然后綁定一個(gè)input事件,看看我們錄入一個(gè)telephone會觸發(fā)多少次input事件:

temp1.addEventListener('oninput', (val) => console.log(val))

觸發(fā)了10次:

那如果每觸發(fā)一次都會調(diào)用后臺接口查詢,那當(dāng)用戶量足夠大,就會給后臺服務(wù)器帶來很大的壓力,導(dǎo)致接口響應(yīng)慢,甚至引起服務(wù)器宕機(jī),也會給用戶帶來不好的體驗(yàn)。

為了不引起過多請求給服務(wù)端造成壓力,我們期望在用戶在輸入完以后再發(fā)起請求,那怎么判斷用戶是否輸入完了?

可以認(rèn)為當(dāng)用戶在一個(gè)固定的時(shí)間內(nèi)都沒有錄入字符是輸入完成/暫時(shí)輸入完成。這個(gè)是老生常談的知識點(diǎn)了————「防抖」和「節(jié)流」。掘金有很多文章專門寫這個(gè)的,筆者在此不過多描述,簡單一筆帶過說下筆者的看法。

防抖 & 節(jié)流

防抖

防抖的函數(shù)在調(diào)用后,如果在防抖時(shí)間內(nèi)沒有再次觸發(fā),就會在過了 防抖時(shí)間 后執(zhí)行;如果在防抖時(shí)間內(nèi)再次觸發(fā),不論觸發(fā)多少次,執(zhí)行的時(shí)機(jī)會一直往后延遲,直到滿足最后一次調(diào)用時(shí)間 小于 當(dāng)前時(shí)間減去防抖時(shí)間才會執(zhí)行。

function debounce(fn, time) {
  let timer
  return function (...argu) {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(() => {
      fn(...argu)
      clearTimeout(timer)
      timer = null
    }, time)
  }
}

節(jié)流

節(jié)流函數(shù)在調(diào)用后,在設(shè)置的節(jié)流時(shí)間后執(zhí)行一次,在此期間,不論觸發(fā)多少次,都直接return了。

function throttle(fn, time) {
  let flag = true
  return function (...argu) {
    if (!flag) {
      return
    }
    flag = false
    let timer = setTimeout(() => {
      fn(...argu)
      flag = true
      clearTimeout(timer)
      timer = null
    }, time)
  }
}

再來看下加了防抖 & 節(jié)流 處理的input事件執(zhí)行情況:

  • 防抖:

  • 防抖 + 節(jié)流:

從上面的兩個(gè)圖不難看出防抖 和節(jié)流的區(qū)別,節(jié)流的函數(shù)如果一直被觸發(fā),每隔一段時(shí)間執(zhí)行一次。而防抖則是一直延遲,最后執(zhí)行一次。

輸入防抖存在的問題

上面的防抖函數(shù)執(zhí)行貌似沒啥問題,前提是我們輸入的是英文,如果是中文輸入就出問題了,看下圖:

當(dāng)中文輸入的時(shí)候,即使已經(jīng)防抖處理了,還可能會執(zhí)行多次。接下來咱們進(jìn)入正題了,如何實(shí)現(xiàn)輸入防抖Vue3指令(并解決中文輸入觸發(fā)多次的問題)。

指令實(shí)現(xiàn)

為什么要以指令的方式實(shí)現(xiàn)?我能想到的有以下兩點(diǎn):

  • 將防抖處理的邏輯封裝在指令內(nèi)部重用,更易用。
  • 指令要支持input輸入框,也要支持封裝input的組件,也就是說需要進(jìn)行底層 DOM 訪問的邏輯,而這一點(diǎn)恰好是指令提供的能力之一。

需要補(bǔ)充Vue 指令相關(guān)知識的同學(xué)點(diǎn)這里自定義指令

期望使用方式:

<template>
  <input v-model="val" v-debounceInput:600="onInput" />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const val = ref('')
function onInput(e: Event): void {
  console.log(e)
}
</script>

即指令的綁定值為 執(zhí)行邏輯,指令參數(shù)為 防抖時(shí)長。

指令實(shí)現(xiàn):

import { debounce, isFunction } from '../../utils/index'

let inputFunction: (event: Event) => {}

// 由于要同時(shí)支持 input 輸入框和封裝 input 的組件,因此需要去找到input這個(gè)元素。
function findInput(el: HTMLElement): HTMLElement | null {
  const quene: HTMLElement[] = []
  quene.push(el)
  while (quene.length > 0) {
    const current = quene.shift()
    if (current?.tagName === 'INPUT') {
      return current
    }
    if (current?.childNodes) {
      quene.push(...current.childNodes)
    }
  }
  return null
}

export default {
  mounted(el: HTMLElement, binding: any) {
    const { value, arg } = binding
    if (value && isFunction(value)) {
      let timeout = 600
      if (arg && !Number.isNaN(arg)) {
        timeout = Number(arg)
      }
      inputFunction = debounce(value, timeout) // 執(zhí)行函數(shù)防抖處理
      const input = findInput(el)
      el._INPUT = input
      if (input) {
        input.addEventListener('input', inputFunction)
      }
    }
  },
  beforeUnmount(el: HTMLElement) {
    if (el._INPUT) {
      el._INPUT.removeEventListener('input', inputFunction)
      el._INPUT = null
    }
  }
}

接著處理中文輸入可能會觸發(fā)多次的問題??山柚?a rel="external nofollow" target="_blank">compositionstart和compositionend來實(shí)現(xiàn)。

  • 輸入法編輯器開始新的輸入合成時(shí)會觸發(fā) compositionstart 事件。例如,當(dāng)用戶使用拼音輸入法開始輸入漢字時(shí),這個(gè)事件就會被觸發(fā)。
  • 當(dāng)文本段落的組成完成或取消時(shí),compositionend 事件將被觸發(fā) (具有特殊字符的觸發(fā),需要一系列鍵和其他輸入,如語音識別或移動中的字詞建議)。

在一開始拼音輸入法時(shí)就設(shè)置composing為true,因此在compositionEnd沒有調(diào)用之前都不會執(zhí)行函數(shù),等compositionEnd調(diào)用,通過dispatchEvent派發(fā)一個(gè)input事件出去,保證邏輯一定會執(zhí)行。

function compositionStart(event: CompositionEvent) {
  event.target.composing = true
}
function compositionEnd(e: CompositionEvent) {
  e.target.composing = false
  const event = new Event('input', { bubbles: true })
  e.target?.dispatchEvent(event)
}

export default {
  mounted(el: HTMLElement, binding: any) {
    //...
      if (input) {
        input.addEventListener('input', inputFunction)
        input.addEventListener('compositionstart', compositionStart)
        input.addEventListener('compositionend', compositionEnd)
      }
    //...
  },
  beforeUnmount(el: HTMLElement) {
    if (el._INPUT) {
      el._INPUT.removeEventListener('input', inputFunction)
      el._INPUT.removeEventListener('compositionstart', compositionStart)
      el._INPUT.removeEventListener('compositionend', compositionEnd)
    }
  }
}

防抖實(shí)現(xiàn) & 判斷是 function

export function debounce(input: (event: Event) => any, timeout: number): (this: HTMLElement, ev: Event) => any {
  let timer: string | number | NodeJS.Timeout | undefined
  return (event: Event) => {
    // @ts-ignore
    if (event.target.composing === true) {
      return
    }
    if (timer) {
      clearTimeout(timer)
      timer = undefined
    }
    timer = setTimeout(() => {
      input(event)
      clearTimeout(timer)
      timer = undefined
    }, timeout)
  }
}

export function isFunction(param: any): boolean {
  return Object.prototype.toString.call(param) === '[object Function]'
}

注冊指令(全局注冊):

createApp(App).directive('debounceInput', debounceInput).mount('#app')

寫個(gè)案例測試一下:

<template>
  <div>防抖</div>
  <input v-model="val" v-debounceInput="onInput" />
  <div>普通</div>
  <input v-model="count" type="text" @input="onInput" />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const val = ref('')
const count = ref('')
function onInput(e: Event): void {
  console.log('調(diào)用了onInput')
}
</script>

看下最終的效果:

差別還是非常明顯的。指令已發(fā)布npm倉庫,有需要可自取。

總結(jié)

??感謝瀏覽,通過本文你可以了解到以下內(nèi)容:

  • 防抖
  • 節(jié)流
  • Vue3指令開發(fā)
  • compositionstart 事件 (需要注意瀏覽器兼容性)
  • compositionend 事件(需要注意瀏覽器兼容性)

到此這篇關(guān)于Vue3指令之搜索框輸入防抖功能實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Vue3搜索框輸入防抖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue cli4.0項(xiàng)目引入typescript的方法

    vue cli4.0項(xiàng)目引入typescript的方法

    這篇文章主要介紹了vue cli4.0項(xiàng)目引入typescript的方法,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Vue中子組件向父組件傳值$emit、.sync的案例詳解

    Vue中子組件向父組件傳值$emit、.sync的案例詳解

    這篇文章主要介紹了Vue中子組件向父組件傳值$emit、.sync的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 詳解Vue數(shù)據(jù)驅(qū)動原理

    詳解Vue數(shù)據(jù)驅(qū)動原理

    這篇文章主要介紹了詳解Vue數(shù)據(jù)驅(qū)動原理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)vue框架的相關(guān)知識,感興趣的朋友可以了解下
    2020-11-11
  • Vue自定義Hook實(shí)現(xiàn)簡化本地存儲

    Vue自定義Hook實(shí)現(xiàn)簡化本地存儲

    這篇文章主要為大家詳細(xì)介紹了如何通過使用 Vue 3 的 Composition API 創(chuàng)建一個(gè)強(qiáng)大而靈活的自定義 Hook,簡化了在 localStorage 或 sessionStorage 中管理數(shù)據(jù)的流程,需要的可以參考下
    2023-12-12
  • 詳解在Vue中有條件地使用CSS類

    詳解在Vue中有條件地使用CSS類

    本篇文章主要介紹了詳解在Vue中有條件地使用CSS類,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • 詳解vue中v-bind:style效果的自定義指令

    詳解vue中v-bind:style效果的自定義指令

    這篇文章主要介紹了vue中v-bind:style效果的自定義指令,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件

    詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件

    這篇文章主要介紹了詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Vue插槽具體用法及實(shí)例分析

    Vue插槽具體用法及實(shí)例分析

    本文主要介紹了Vue框架中插槽的使用方法和應(yīng)用場景。通過具體實(shí)例分析,詳細(xì)講解了插槽的具體用法,幫助讀者深入理解Vue中插槽的使用和實(shí)現(xiàn)方式
    2023-05-05
  • vue項(xiàng)目首屏加載過慢的一些解決方案

    vue項(xiàng)目首屏加載過慢的一些解決方案

    最近碰到vue項(xiàng)目打包上線后,第一次打開首頁后會出現(xiàn)空白、加載時(shí)間過長的情況,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目首屏加載過慢的一些解決方案,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • vue?懸浮窗且?guī)ё詣游焦δ軐?shí)現(xiàn)demo

    vue?懸浮窗且?guī)ё詣游焦δ軐?shí)現(xiàn)demo

    這篇文章主要為大家介紹了vue?懸浮窗且?guī)ё詣游焦δ軐?shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06

最新評論