Endereço de demonstração do GitHub
pré-visualização online
Site oficial do Lodash
referência:
Vue anti-vibração e limitação de introdução detalhada
Vue implementa elegantemente anti-vibração
e limitação Introdução de
anti-vibração e limitação O princípio de realização e cenários de aplicação de
js anti-vibração e limitação
O que é antivibração e estrangulamento?
Função de aceleração (throttle) e função anti-vibração (debounce) são para limitar a frequência de execução da função, para otimizar a velocidade de resposta causada pela alta frequência de disparo da função, que não consegue acompanhar a frequência de disparo, atraso, animação suspensa ou congelamento
Um esquema de otimização para eventos de acionamento frequente.
Antivibração (debounce)
Anti-vibração é para evitar agitação e evitar o acionamento repetido de eventos.
O antivibração pode ser resumido como após um evento de alta frequência ser acionado, a função será executada apenas uma vez em n segundos. Se o evento de alta frequência for acionado novamente em n segundos, o tempo será recalculado.
Execute o evento após n segundos. Se for acionado repetidamente após n segundos, a cronometragem será reiniciada.
Simplificando, se um evento for acionado várias vezes seguidas e rapidamente, apenas o último será executado.
- Método de implementação: defina um método de chamada atrasada sempre que um evento for acionado e cancele o método de chamada atrasada anterior
- Se o evento for acionado continuamente dentro do intervalo de tempo especificado, o método de chamada será continuamente atrasado
cenas a serem usadas
- entrada Pesquisar entrada, o usuário insere continuamente o valor
- janela aciona o evento de redimensionamento
- mousemove evento deslizante do mouse
- Rolar solicitação deslizante da barra de rolagem, puxe para cima e para baixo para carregar mais
- Validação de formulário, evento de envio de botão
acelerador
A limitação serve para reduzir o tráfego, reduzir os eventos acionados com frequência e executá-los em intervalos regulares. Irá controlar a frequência com que o evento é acionado. Portanto, a limitação diluirá a frequência de execução da função.
Ele é executado apenas uma vez em n segundos e, se for acionado repetidamente em n segundos, só terá efeito uma vez.
Se for acionado várias vezes em rápida sucessão, será acionado apenas uma vez dentro do tempo especificado. Se for limitado a 1s, será executado apenas uma vez em 1s e, não importa o que aconteça, a operação correspondente será executada em 1s.
- Método de implementação: toda vez que um evento é acionado, se houver uma função de atraso esperando para ser executada, retorne diretamente
- Se o evento for acionado continuamente dentro do intervalo de tempo especificado, o método de chamada será executado uma vez dentro do intervalo de tempo especificado
cenas a serem usadas
- obter código de verificação
- O mouse é clicado continuamente para acionar, mousedown (acionado apenas uma vez dentro do tempo especificado)
- mousemove evento deslizante do mouse
- Solicitação de slide da barra de rolagem, puxe para cima e para baixo para carregar mais
- Funções do botão, como pesquisar, enviar, etc.
Diferença entre estabilização e estrangulamento:
mesmo ponto:
- Ambos podem ser alcançados usando setTimeout
- O objetivo é reduzir a frequência de execução da função callback e economizar recursos de computação
diferença:
-
Anti-vibração é processar o retorno de chamada após um período de operação contínua, usando clearTimout e setTimeout para conseguir.
-
A limitação é uma operação contínua que é executada apenas uma vez por período de tempo e usada em eventos com maior frequência para melhorar o desempenho.
-
O antivibração é usado para comportamento ativo imprevisível do usuário, como conteúdo de entrada do usuário para resultados de pesquisa dinâmicos no servidor. A velocidade de digitação do usuário é imprevisível e irregular.
-
A limitação pode ser usada para alguns comportamentos ativos de não usuários ou comportamentos previsíveis de usuários ativos, como enviar uma solicitação de ponto oculto quando o usuário desliza a janela do produto e a altura fixa deslizante é uma lógica conhecida e tem regularidade.
-
O antivibração é focado no último acionador do evento, enquanto a limitação é executada apenas uma vez dentro de um tempo especificado.
-
Anti-vibração é transformar várias execuções na última execução, e limitação é transformar várias execuções em execução em intervalos
Utilitários antivibração e estrangulamento
/**
* 防抖 (传入所要防抖的方法/回调与延迟时间)
* @param {Function} func
* @param {number} delay
* @return {*}
*/
export function debounce2(func, delay) {
let timer = null
// 借助闭包,使得变量timer不被回收
return function() {
// 保存当前环境下的实例对象,this即为引入该方法的那个组件实例对象
const th = this
// 保存传入参数
const args = arguments
// 第一次timer为null,跳过该判断,执行setTimeout()
if (timer) {
// 之后如果timer存在,则把上一次的销毁,也就是setTimeout(),则里面的函数执行也会抛弃
clearTimeout(timer)
}
timer = setTimeout(() => {
// apply(),改变this指向,指向正在操作的组件实例,传入参数
func.apply(th, args)
timer = null
}, delay)
}
}
/*
由于使用闭包,使得timer不被回收,在A组件中每次调用该方法时会去判断timer是否存在,如果存在,
表示上一次输入在等待执行fn(),期间如果继续输入,且在1s内,则会把上一次未执行的(setTimeout中的)fn()销毁,
重新定时1s,以此来达到输入结束过1s才执行fn(),即触发事件或者发送请求。
*/
/**
* 节流 (传入所要节流的方法/回调与延迟时间)
* @param {Function} func
* @param {number} delay
* @return {*}
*/
export function throttle(func, delay) {
let flag = true
return function() {
const th = this
const args = arguments
if (!flag) {
// 未超过时间间隔,flag无效,不执行fn
return false
}
func.apply(th, args)
flag = false // 在时间间隔内把状态位flag设为无效(false)
setTimeout(() => {
flag = true // 超过时间间隔把状态位flag设为有效(true)
}, delay)
}
}
instalação Lodash
Ambiente do navegador:
<script src="lodash.js"></script>
via npm:
$ npm i -g npm
$ npm i --save lodash
debounced
Documentação da função Lodash debounce Documentação
da função Lodash throttlingthrottle
Antivibração e estrangulamento usando Lodash
Quando não processado, um evento será acionado quando o texto de entrada for alterado ou um evento será acionado quando clicado
Após o processamento,
o antivibração usado para entrada de texto, o intervalo definido de 0,5 segundos, cliques múltiplos serão acionados apenas na última vez. A
limitação usada ao clicar no botão de consulta, o intervalo definido de 3 segundos, será acionado apenas uma vez dentro de 3 segundos após vários cliques
Código de chave antivibração
<el-input v-model="queryParams2.name" maxlength="20" placeholder="请输入"
clearable @input="onChange2" @keyup.enter.native="onSearch2" />
// lodash文档: https://www.lodashjs.com/
//
// 搜索框防抖 - lodash实现
// 不要在debounce里写箭头函数,否则this的指向就是undefined,而不是Vue实例对象。
// 注意这里若是使用箭头函数的话, this为 undefined https://github.com/vue-styleguidist/vue-docgen-api/issues/23
onChange2: lodash.debounce(function() {
// Do some things
this.getListByKeyword()
}, 500),
getListByKeyword() {
// 请求...
console.log('根据关键字 请求...')
console.log(this.queryParams2.name)
console.log(JSON.stringify(this.queryParams2))
},
Código da chave de limitação - Caminho 1
<el-button class="spp-form-btn" size="small" type="primary" @click="onSearch2()">查询</el-button>
// 按钮节流 - lodash实现 - 方式1
onSearch2: lodash.throttle(function() {
// Do some things
this.requestList()
}, 3000),
requestList() {
// 请求...
console.log('点击搜索按钮 请求...')
console.log(JSON.stringify(this.queryParams2))
},
Código da Tecla de Aceleração - Modo 2
<el-button class="spp-form-btn" size="small" type="primary" style="width: 120px;"
@click="onSearch22()">查询(方式2)</el-button>
created() {
// 按钮节流 - lodash实现 - 方式2
this.onSearch22 = lodash.throttle(this.onSearch22, 3000)
},
requestList() {
// 请求...
console.log('点击搜索按钮 请求...')
console.log(JSON.stringify(this.queryParams2))
},
// 按钮节流 - lodash实现 - 方式2
onSearch22() {
// Do some things
this.requestList3()
},
todos os códigos
<template>
<div class="spp-theme-body spp-theme-pad">
<h1 style="margin:10px 0px 30px;">防抖与节流</h1>
<div> 未处理前 </div>
<el-form :inline="true" size="small" :model="queryParams" class="spp-form-search spp-theme-top">
<el-form-item>
<span class="spp-form-label" style="width:80px">
<i class="icon" /><i class="label">名称:</i>
</span>
<el-input v-model="queryParams.name" maxlength="20" placeholder="请输入" clearable @input="onChange" @keyup.enter.native="onSearch" />
</el-form-item>
<el-form-item>
<el-button class="spp-form-btn" size="small" type="primary" @click="onSearch()">查询</el-button>
</el-form-item>
</el-form>
<div class="spp-theme-top"> lodash实现 - 搜索框防抖(0.5秒) / 点击按钮节流(3秒内) </div>
<el-form :inline="true" size="small" :model="queryParams2" class="spp-form-search spp-theme-top">
<el-form-item>
<span class="spp-form-label" style="width:80px">
<i class="icon" /><i class="label">名称:</i>
</span>
<el-input v-model="queryParams2.name" maxlength="20" placeholder="请输入" clearable @input="onChange2" @keyup.enter.native="onSearch2" />
</el-form-item>
<el-form-item>
<el-button class="spp-form-btn" size="small" type="primary" @click="onSearch2()">查询</el-button>
</el-form-item>
<el-form-item>
<el-button class="spp-form-btn" size="small" type="primary" style="width: 120px;" @click="onSearch22()">查询(方式2)</el-button>
</el-form-item>
</el-form>
<div class="spp-theme-top"> utils实现 - 搜索框防抖(0.5秒) / 点击按钮节流(3秒内) </div>
<el-form :inline="true" size="small" :model="queryParams2" class="spp-form-search spp-theme-top">
<el-form-item>
<span class="spp-form-label" style="width:80px">
<i class="icon" /><i class="label">名称:</i>
</span>
<el-input v-model="queryParams3.name" maxlength="20" placeholder="请输入" clearable @input="onChange3" @keyup.enter.native="onSearch3" />
</el-form-item>
<el-form-item>
<el-button class="spp-form-btn" size="small" type="primary" @click="onSearch3()">查询</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import lodash from 'lodash'
import {
debounce2, throttle } from '@/utils/index'
export default {
components: {
},
data() {
return {
tableHeight: 170,
tableLoading: false,
tableData: [],
queryParams: {
name: '',
page: 1,
limit: this.pageGroup.size
},
queryParams2: {
name: '',
page: 1,
limit: this.pageGroup.size
},
queryParams3: {
name: '',
page: 1,
limit: this.pageGroup.size
}
}
},
created() {
// 按钮节流 - lodash实现 - 方式2
this.onSearch22 = lodash.throttle(this.onSearch22, 3000)
},
mounted() {
},
methods: {
onChange(val) {
console.log(val)
},
onSearch() {
console.log('点击搜索按钮 请求...')
console.log(JSON.stringify(this.queryParams))
},
// lodash文档: https://www.lodashjs.com/
//
// 搜索框防抖 - lodash实现
// 不要在debounce里写箭头函数,否则this的指向就是undefined,而不是Vue实例对象。
// 注意这里若是使用箭头函数的话, this为 undefined https://github.com/vue-styleguidist/vue-docgen-api/issues/23
onChange2: lodash.debounce(function() {
// Do some things
this.getListByKeyword()
}, 500),
getListByKeyword() {
// 请求...
console.log('根据关键字 请求...')
console.log(this.queryParams2.name)
console.log(JSON.stringify(this.queryParams2))
},
// 按钮节流 - lodash实现 - 方式1
onSearch2: lodash.throttle(function() {
// Do some things
this.requestList()
}, 3000),
requestList() {
// 请求...
console.log('点击搜索按钮 请求...')
console.log(JSON.stringify(this.queryParams2))
},
// 按钮节流 - lodash实现 - 方式2
onSearch22() {
// Do some things
this.requestList3()
},
// 防抖
// 项目工具类
// 如果需要加参数,则在function空的形参列表里加入
onChange3: debounce2(function(val) {
console.log('录入的文字', val)
// Do some things
this.getListByKeyword3()
}, 500),
getListByKeyword3() {
// 请求...
console.log('根据关键字 请求...')
console.log(this.queryParams3.name)
console.log(JSON.stringify(this.queryParams3))
},
onSearch3: throttle(function() {
// Do some things
this.requestList3()
}, 3000),
requestList3() {
// 请求...
console.log('点击搜索按钮 请求...')
console.log(JSON.stringify(this.queryParams3))
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-input__icon:after {
height: auto;
}
</style>