在观察者内部调用`_.debounce` 不起作用 [英] Calling `_.debounce` inside a watcher not working
问题描述
考虑以下示例:https:///codesandbox.io/s/nuxt-playground-forked-rld4j?file=/pages/index.vue
我试图制作一个涉及我的一般用例的最小示例.这就是数据格式奇怪的原因.输入 000 或 111,您可以看到它是如何逐步搜索数据的.
基本上它会生成大量数据(我实际上想要更多)但您已经注意到性能下降.现在我想我可以通过消除我的观察者来开始提高性能.您可以在上面示例的第 58 行中看到这一点.它被注释掉了,因为.您可以将第 57 行注释掉并添加去抖动以查看它不起作用.
上面例子的代码如下:
<div><输入类型=文本"v-model=searchString"/>搜索字符串:{{ 搜索字符串 }}<div v-for="(items, index) in this.filteredPosts";:key="items[0]"><div v-for=项目中的项目":key=项目">{{ 物品 }}
<br/>
模板><脚本>从lodash"导入_导出默认{异步异步数据(){//只生成一些随机数据让动物 = [狗"、猫"、鱼"、计算机"、c++"];//此时,帖子没有被过滤.我们只要打电话//因为我们使用这个变量名来过滤它们//渲染,我们希望变量filteredPosts 可用//越早越好.让filteredPosts = [];常量 N = 1000;常量 M = 6;for (让 i = 0; i < N; ++i) {让 tmpSubArray = [String(i)];for (让 j = 0; j 现在我不明白为什么它不起作用.有人可以指出我的问题吗?如果有任何其他问题,请指出.:) 首先,增加items时组件渲染的滞后,不是过滤功能造成的,而是直接关系到DOM组件的渲染,以及这不是通过消除过滤来解决的,而是通过减少渲染项目的数量来解决的.例如,在下面的代码和框中,我将渲染的项目切成前 20 个结果,您可以测试即使没有去抖动,即使初始数据非常大也没有延迟.所以朝那个方向思考(元素的延迟渲染). 其次,如果还需要去抖过滤,那么去抖的实现是不对的. lodash中Function的_.debounce()方法用于创建一个去抖动函数将给定的函数延迟到指定的函数之后等待时间以毫秒为单位自上次以来已经过去了调用了去抖动函数. 所以,基本上 通过调用观察者 每次触发观察者时,您都在创建一个新的去抖动函数,但从不调用它. 正确的实现包括以下几点: https://codesandbox.io/s/gifted-goldwasser-bj2sy?file=/src/components/HelloWorld.vue consider the following example: https://codesandbox.io/s/nuxt-playground-forked-rld4j?file=/pages/index.vue I tried to make a minimal example that involves my general use case. That's the reason for the odd format of the data. Type 000 or 111 and you can see how it gradually searches through the data. Basically it generates a lot of data (I actually want to have more than that) but you already notice a drop in performance. Now I thought I could start improving the performance by debouncing my watcher. You can see that in line 58 in the above example. It's commented out because. You can comment line 57 out and add the debouncing to see that it doesn't work. Here's the code of the above example: Now I fail to see why it wouldn't work. Can someone point me to the issue? Please point out all other issues if there are any. :) First, the lag in component rendering when increasing the number of items, is not caused by filtering function, but are directly related to the rendering of DOM components, and this is not solved by debouncing the filtering, but by decreasing the number of rendered items. For ex., in the below codesandbox, I sliced the rendered items to the first 20 results, and you can test that even without debouncing it has no lag even with very large initial data. So think in that direction (lazy rendering of elements). Second, if still you need to debounce the filtering, then the implementation of debounce is not correct. The _.debounce() method of Function in lodash is used to create a
debounced function which delays the given func until after the stated
wait time in milliseconds have passed since the last time this
debounced function was called. So, basically By calling in watcher you are creating a new debounced function every time the watcher is triggered, but never call it. The correct implementation involve the following: https://codesandbox.io/s/gifted-goldwasser-bj2sy?file=/src/components/HelloWorld.vue 这篇关于在观察者内部调用`_.debounce` 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!_.debounce
从现有函数创建一个新的(去抖动)函数.debouncedFunc = _.debounce(existingFunc, timeout)
_.debounce(function () {this.filteredPosts = this.filterByValue();});
//有一些需要去抖动的函数现有函数(){//代码}//从现有版本创建一个去抖动版本const deboncedFunc = _.debounce(existingFunc, 1000)//调用去抖动版本debouncedFunc()
<template>
<div>
<input type="text" v-model="searchString" />
SearchString: {{ searchString }}
<div v-for="(items, index) in this.filteredPosts" :key="items[0]">
<div v-for="item in items" :key="item">
{{ item }}
</div>
<br />
</div>
</div>
</template>
<script>
import _ from "lodash";
export default {
async asyncData() {
// Just generate some random data
let animals = ["dog", "cat", "fish", "computer", "c++"];
// At this point the posts aren't filtered. We just call
// them filtered because we use this variable name to
// render and we want the variable filteredPosts available
// as early as possible.
let filteredPosts = [];
const N = 1000;
const M = 6;
for (let i = 0; i < N; ++i) {
let tmpSubArray = [String(i)];
for (let j = 0; j < M; ++j) {
tmpSubArray.push(i + " " + j);
}
filteredPosts.push(tmpSubArray);
}
return { filteredPosts };
},
data() {
return {
searchString: "",
posts: [],
};
},
watch: {
searchString() {
// If this.posts is empty, which is only in the very
// beginning the case, store a copy of the original
// posts (which at this point are stored in
// this.filteredPosts )
// => from now one this.posts is the original data which
// won't get changed ever and this.filteredPosts is being
// changed.
if (this.posts.length === 0) {
this.posts = this.filteredPosts;
}
this.filteredPosts = this.filterByValue();
/* _.debounce(function () {
console.log("debounce");
this.filteredPosts = this.filterByValue();
});
*/
},
},
methods: {
filterByValue() {
// Get searchString
const searchString = this.searchString.toLowerCase();
// Loop over all posts
let foo = this.posts.filter((items) => {
return items.some((item) => {
if (item.toLowerCase().includes(searchString)) {
return true;
}
return false;
});
});
return foo;
},
},
};
</script>
_.debounce
create a new (debounced) function from an existing one.debouncedFunc = _.debounce(existingFunc, timeout)
_.debounce(function () {
this.filteredPosts = this.filterByValue();
});
// Having some function that need debouncing
existingFunc(){
// code
}
// Creating a debounced version from the existing one
const deboncedFunc = _.debounce(existingFunc, 1000)
// Calling the debounced version
debouncedFunc()