Debouncing/throttling 使用 Vue 的方法 Class 组件语法
Debouncing/throttling a method using Vue Class Component Syntax
我正在开发一个组件,当搜索栏中的文本发生变化时,该组件会查询外部 API,我正在尝试对该查询进行去抖动处理,使其只能每 2 秒执行一次。我正在尝试使用 lodash 的 debounce
函数来做到这一点,并且发现了多篇博文和关于将它与 Vue 组件一起使用的问题,但事情很复杂,因为我使用的是 Typescript 和 Vue Class组件语法 (https://class-component.vuejs.org/)。老实说,我对这两个都很陌生。
我找到了 a blog post outlining how to do this with object-based Vue component syntax,但它不适用于 Class 组件语法。基于对象的语法允许您将方法包装在 _.debounce
中,如下所示:
export default {
methods: {
throttledMethod: _.debounce(() => {
console.log('I only get fired once every two seconds, max!')
}, 2000)
}
}
有没有办法用 Vue Class 组件语法做类似的事情?
以下是我的代码的相关部分(没有任何去抖动尝试):
<template>
<input
v-model="searchQuery"
@keydown="doSearch"
>
</template>
<script lang="ts">
import axios from 'axios';
import _ from 'lodash';
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class FooSearch extends Vue {
// data
searchQuery = '';
results = [];
// methods
async doSearch() {
try {
const response = await axios.get('https://api.example.org/search', {
params: {
query: this.searchQuery,
}
});
this.results = response.data.results;
} catch(error) {
console.log('error');
console.log(error);
}
}
</script>
已讨论here。
基本上,您需要定义基本函数(就像您对 doSearch
所做的那样),然后定义新的去抖动函数:
public doSearchDebounced = _.debounce(this.doSearch, 2000)
现在你只需要调用 doSearchDebounced
而不是 doSearch
你可以这样做
<script lang='ts'>
import { debounce } from 'decko'
@debounce(1000)
async doSearch() {
....
}
</script>
虽然上面已经回答了,但是我觉得还是应该好好利用vue-class-component
中的createDecorator
,整合lodash
来简化Debounce和Throttle的使用
创建decorator.ts
import { createDecorator } from "vue-class-component";
import _ from "lodash";
export const Debounce = (waitMs: number) =>
createDecorator((options, key) => {
if (options.methods && options.methods[key]) {
const originalMethod = options.methods[key];
const debounceMethod = _.debounce(originalMethod, waitMs, {
leading: false,
trailing: true,
});
options.methods[key] = async function (...args: any) {
await debounceMethod.apply(this, args);
};
}
});
export const Throttle = (waitMs: number) =>
createDecorator((options, key) => {
if (options.methods && options.methods[key]) {
const originalMethod = options.methods[key];
const throttleMethod = _.throttle(originalMethod, waitMs, {
leading: true,
trailing: false,
});
options.methods[key] = async function (...args: any) {
await throttleMethod.apply(this, args);
};
}
});
重构代码并使用装饰器。
<template>
<input
v-model="searchQuery"
@keydown="doSearch"
>
</template>
<script lang="ts">
import axios from 'axios';
import { Component, Vue } from 'vue-property-decorator';
import { Debounce } from "@/decorator";
@Component
export default class FooSearch extends Vue {
// data
searchQuery = '';
results = [];
// add the Debounce annotation
@Debounce(1500)
async doSearch() {
try {
const response = await axios.get('https://api.example.org/search', {
params: {
query: this.searchQuery,
}
});
this.results = response.data.results;
} catch(error) {
console.log('error');
console.log(error);
}
}
</script>
我正在开发一个组件,当搜索栏中的文本发生变化时,该组件会查询外部 API,我正在尝试对该查询进行去抖动处理,使其只能每 2 秒执行一次。我正在尝试使用 lodash 的 debounce
函数来做到这一点,并且发现了多篇博文和关于将它与 Vue 组件一起使用的问题,但事情很复杂,因为我使用的是 Typescript 和 Vue Class组件语法 (https://class-component.vuejs.org/)。老实说,我对这两个都很陌生。
我找到了 a blog post outlining how to do this with object-based Vue component syntax,但它不适用于 Class 组件语法。基于对象的语法允许您将方法包装在 _.debounce
中,如下所示:
export default {
methods: {
throttledMethod: _.debounce(() => {
console.log('I only get fired once every two seconds, max!')
}, 2000)
}
}
有没有办法用 Vue Class 组件语法做类似的事情?
以下是我的代码的相关部分(没有任何去抖动尝试):
<template>
<input
v-model="searchQuery"
@keydown="doSearch"
>
</template>
<script lang="ts">
import axios from 'axios';
import _ from 'lodash';
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class FooSearch extends Vue {
// data
searchQuery = '';
results = [];
// methods
async doSearch() {
try {
const response = await axios.get('https://api.example.org/search', {
params: {
query: this.searchQuery,
}
});
this.results = response.data.results;
} catch(error) {
console.log('error');
console.log(error);
}
}
</script>
已讨论here。
基本上,您需要定义基本函数(就像您对 doSearch
所做的那样),然后定义新的去抖动函数:
public doSearchDebounced = _.debounce(this.doSearch, 2000)
现在你只需要调用 doSearchDebounced
而不是 doSearch
你可以这样做
<script lang='ts'>
import { debounce } from 'decko'
@debounce(1000)
async doSearch() {
....
}
</script>
虽然上面已经回答了,但是我觉得还是应该好好利用vue-class-component
中的createDecorator
,整合lodash
来简化Debounce和Throttle的使用
创建decorator.ts
import { createDecorator } from "vue-class-component";
import _ from "lodash";
export const Debounce = (waitMs: number) =>
createDecorator((options, key) => {
if (options.methods && options.methods[key]) {
const originalMethod = options.methods[key];
const debounceMethod = _.debounce(originalMethod, waitMs, {
leading: false,
trailing: true,
});
options.methods[key] = async function (...args: any) {
await debounceMethod.apply(this, args);
};
}
});
export const Throttle = (waitMs: number) =>
createDecorator((options, key) => {
if (options.methods && options.methods[key]) {
const originalMethod = options.methods[key];
const throttleMethod = _.throttle(originalMethod, waitMs, {
leading: true,
trailing: false,
});
options.methods[key] = async function (...args: any) {
await throttleMethod.apply(this, args);
};
}
});
重构代码并使用装饰器。
<template>
<input
v-model="searchQuery"
@keydown="doSearch"
>
</template>
<script lang="ts">
import axios from 'axios';
import { Component, Vue } from 'vue-property-decorator';
import { Debounce } from "@/decorator";
@Component
export default class FooSearch extends Vue {
// data
searchQuery = '';
results = [];
// add the Debounce annotation
@Debounce(1500)
async doSearch() {
try {
const response = await axios.get('https://api.example.org/search', {
params: {
query: this.searchQuery,
}
});
this.results = response.data.results;
} catch(error) {
console.log('error');
console.log(error);
}
}
</script>