【问题标题】:Search functionality with rest api prevent DDOSing the server使用 rest api 的搜索功能可防止对服务器进行 DDOS
【发布时间】:2019-12-25 00:14:32
【问题描述】:

问题

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

我尝试实施的解决方案来自this post on Stackoverflow

代码

这将我引向以下代码。

我有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 中计算属性中的设置器没有被调用,并且没有从服务器获取数据。关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: ajax vue.js vuejs2 vue-component debouncing


    【解决方案1】:

    您的第一个代码块导入debounce,但没有使用它。它还声明了一个未使用的道具searchName。这些不是核心问题,但杂乱无章会让我们更难弄清楚发生了什么。

    您的第二个代码块使用v-model,但没有遵循required conventionsv-model 使用组件:

    1. 组件必须采用名为value的道具
    2. 组件必须通过emit input 事件向value 发出更改信号

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

    从这里,您甚至不需要存储输入值。当它改变时你只想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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多