带有 rest api 的搜索功能可防止对服务器进行 DDOS 攻击

Search functionality with rest api prevent DDOSing the server

问题

我有一个搜索组件和实现搜索组件的组件。当我在 1/2 秒未输入(去抖动)后在搜索栏中输入内容时,服务器应该被命中并返回结果。

我尝试实施的解决方案来自

代码

这使我得到以下代码。

我有search.vue

<template>
    <label for="search">
        <input
                id="search"
                class="w-full py-2 px-1 border-gray-900 border"
                type="text"
                name=":searchTitle"
                v-model="searchFilter"
                :placeholder="searchPlaceholder"
                autocomplete="off"
                v-on:keydown="filteredDataset"
        />
    </label>
</template>
<script>
  import {debounce} from 'lodash';
  export default {
    props: {
      searchPlaceholder: {
        type: String,
        required: false,
        default: ''
      },
      searchName: {
        type: String,
        required: false,
        default: 'search'
      }
    },
    data() {
      return {
        searchFilter: '',
      }
    },
    methods: {
      filteredDataset() {
        console.log('event fired');
        this.$emit('searchValue', this.searchFilter);
      }
    },
  }
</script>

product.vue

<template>
    <div>
        <div class="my-4">
            <search
                    search-placeholder=""
                    search-name=""
                    v-on:searchValue="filterValue = $event"
                    v-model="productsFiltered"
            >

            </search>
            <div class="flex w-full py-1 border px-2 my-2" v-for="product in productsFiltered"> (...)
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import {debounce} from 'lodash';
  export default {
    data() {
      return {
        products: [],
        filterValue: '',
        filteredProducts: ''
      }
    },
    computed: {
      productsFiltered: {
            get(){
              console.log('getter called');
                return this.filteredProducts;
            },
            set: _.debounce(function(){
              console.log('setter called');
              if (this.filterValue.length < 1) {
                this.filteredProducts = [];
              }

              axios.get(`${apiUrl}search/` + this.filterValue)
                .then(response => {
                  this.products = response.data.products;
                  const filtered = [];
                  const regOption = new RegExp(this.filterValue, 'ig');
                  for (const product of this.products) {
                    if (this.filterValue.length < 1 || product.productname.match(regOption)) {
                      filtered.push(product);
                    }
                  }
                  this.filteredProducts = filtered;
                });


            }, 500)
      }
    },

  }

</script>

结果 结果是 product.vue 中计算的 属性 中的 setter 没有被调用,也没有从服务器获取数据。关于如何解决这个问题的任何想法?

您的第一个代码块导入 debounce 但未使用它。它还声明了一个未使用的道具 searchName。这些不是核心问题,但混乱使得弄清楚发生了什么变得更加困难。

您的第二个代码块使用 v-model 但没有遵循 required conventionsv-model 与组件一起工作:

  1. 组件必须使用名为 value
  2. 的 prop
  3. 组件必须 emit input 事件来指示对 value
  4. 的更改

您有组件 emit searchValue 事件,并使用设置数据项的 v-on 处理它们。您似乎希望 v-model 调用 setter,但正如我所指出的,您还没有将其连接起来。

从这里可以看出,您甚至不需要存储输入值。您只想在它更改时 emit 它。这是一个演示:

const searchComponent = {
  template: '#search-template',
  props: {
    searchPlaceholder: {
      type: String,
      required: false,
      default: ''
    }
  },
  methods: {
    filteredDataset(searchFilter) {
      console.log('event fired');
      this.$emit('input', searchFilter);
    }
  }
};

new Vue({
  el: '#app',
  data() {
    return {
      products: [],
      filterValue: '',
      filteredProducts: ''
    }
  },
  components: {
    searchComponent
  },
  computed: {
    productsFiltered: {
      get() {
        console.log('getter called');
        return this.filteredProducts;
      },
      set: _.debounce(function() {
        console.log('setter called');
        if (this.filterValue.length < 1) {
          this.filteredProducts = [];
        }
        setTimeout(() => {
          console.log("This is the axios call");
          this.filteredProducts = ['one','two','three'];
        }, 200);

      }, 500)
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<template id="search-template">
    <label for="search">
        <input
            id="search"
            class="w-full py-2 px-1 border-gray-900 border"
            type="text"
            name=":searchTitle"
            :placeholder="searchPlaceholder"
            autocomplete="off"
            @input="filteredDataset"
        />
    </label>
</template>

<div id="app">
  <div class="my-4">
    <search-component search-placeholder="enter something" v-model="productsFiltered">

    </search-component>
    <div class="flex w-full py-1 border px-2 my-2" v-for="product in productsFiltered"> (...)
    </div>
  </div>
</div>