首页 > 解决方案 > 在观察者内部调用`_.debounce`不起作用

问题描述

考虑以下示例:https ://codesandbox.io/s/nuxt-playground-forked-rld4j?file=/pages/index.vue

我试图做一个涉及我的一般用例的最小示例。这就是数据格式奇怪的原因。键入 000 或 111,您可以看到它是如何逐步搜索数据的。

基本上它会生成大量数据(我实际上想要更多),但您已经注意到性能下降了。现在我想我可以通过对我的观察者进行去抖动来开始提高性能。您可以在上面示例的第 58 行看到这一点。它被注释掉了,因为。您可以将第 57 行注释掉并添加去抖动以查看它不起作用。

这是上面示例的代码:

    <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>

现在我不明白为什么它不起作用。有人可以指出我的问题吗?如果有任何其他问题,请指出所有其他问题。:)

标签: vue.jsnuxt.js

解决方案


debounce没有按预期的方式工作。

debounce返回去抖函数。如果未调用函数,debounce(...)则为空操作。

去抖函数需要事先创建,而不是在它应该被去抖的上下文中,这样使用debounce时不可能推迟函数调用,因为每次调用它都会创建一个新的去抖函数。

它应该是:

  data() {
    return {
      ...
      debouncedFilterByValue: _.debounce(this.filterByValue)
    }
  },
  watch: {
    searchString() {
      ...
      this.filteredPosts = this.debouncedFilterByValue();
    },
  },

推荐阅读