首页 > 解决方案 > 多字段搜索表单,无需为每个搜索条件复制组件

问题描述

我有一个多字段表单,每个字段都用于通过 API 进行搜索,该 API 将在下面显示一个表格,其中包含与搜索匹配的数据。我让它适用于一个领域。但我需要它适用于表单中的所有字段。我只是不知道如何使这个动态化,所以我不必重复我的组件 10 次。

让我展示一下相关代码:

  <form class="uk-form-stacked">
    <div>
       <input-field label="Product ID" v-model="id"></input-field>
       <input-field label="Product Name" v-model="name"></input-field>
       <select-field label="Supplier ID" v-model="supplierId" :options="supplierOptions"></select-field>
       <select-field label="Category ID" v-model="categoryId" :options="categoryOptions"></select-field>
       <input-field label="Quantity Per Unit" v-model="quantityPerUnit"></input-field>
       <input-field label="Unit Price" v-model="unitPrice"></input-field>
       <input-field label="Units in stock" v-model="unitsInStock"></input-field>
       <input-field label="Units on order" v-model="unitsOnOrder"></input-field>
       <input-field label="Reorder level" v-model="reorderLevel"></input-field>
       <checkbox-field label="Discontinued" v-model="discontinued" :options="this.discontinuedOptions" :checked="checked"></checkbox-field>
    </div>
    <div>
       <button type="reset" class="uk-button uk-button-secondary uk-button-small" @click.prevent="clearForm"> Clear </button>
       <button type="submit" @click.prevent="search" class="uk-button uk-button-primary uk-button-small"> Search </button>
    </div>

    <div class="results-area">
       <result-item
          :data="filteredResultsById" // can this be made to accept a conditional computed value?
          :total-pages="Math.ceil(filteredResultsById.length / 10)"
          :total="filteredResultsById.length"
          :per-page="10"
          :current-page="currentPage"
          @pagechanged="onPageChange"
       />
    </div>
  </form>

  computed: {
      ...mapGetters(["getProducts"]),
      filteredResultsById: function() {
         return this.getProducts.filter((result) => {

            // I imagine there should be a loop in here maybe?
            let resultById = result.id;
            return resultById.toString().match(this.id);
         });
      },
  },

所以,这适用于第一个字段(产品 ID),但我需要让其他字段也可搜索,我不想像这样复制组件

    <div class="results-area">
       <result-item
          :data="filteredResultsById"  // <-- By Id
          :total-pages="Math.ceil(filteredResultsById.length / 10)"
          :total="filteredResultsById.length"
          :per-page="10"
          :current-page="currentPage"
          @pagechanged="onPageChange"
       />
       <result-item
          :data="filteredResultsByName" // <-- By Name
          :total-pages="Math.ceil(filteredResultsByName.length / 10)"
          :total="filteredResultsByName.length"
          :per-page="10"
          :current-page="currentPage"
          @pagechanged="onPageChange"
       />
       <result-item
          :data="filteredResultsBySupplierId"  // <-- By supplierId
          :total-pages="Math.ceil(filteredResultsBySupplierId.length / 10)"
          :total="filteredResultsBySupplierId.length"
          :per-page="10"
          :current-page="currentPage"
          @pagechanged="onPageChange"
       />
       ...

       
    </div>

同样,有 10 个类似的计算方法是重复的。我该如何改进呢?

单独的问题 - 我知道它可以随着 v-model 通过插值而变化,这很酷,但我想在单击保存按钮时完成它,但同样,我不想制作 10 个动态显示的按钮. 这太疯狂了。

编辑

所以我想出了如何制作它,这样我就不必复制组件 10 次了!这是现在编辑的计算方法。我觉得 switch 语句在渲染时可能会更便宜,所以它不会渲染所有这些条件。我说得对吗?

无论如何,我仍然无法通过搜索按钮点击它,而且我无法通过<select>下拉列表中的值进行搜索

filteredResults: function() {
  return this.getProducts.filter((result) => {
    let resultById = result.id;
    let resultByName = result.name;
    let resultBySupplierId = result.supplierId;
    let resultByCategoryId = result.categoryId;
    let resultByQtyPerUnit = result.quantityPerUnit;
    let resultByUnitPrice = result.unitPrice;
    let resultByUnitsInStock = result.unitsInStock;
    let resultByUnitsOnOrder = result.unitsOnOrder;
    let resultByReorderLevel = result.reorderLevel;
    let resultByDisc = result.discontinued;
    return (
      resultById.toString().match(this.id) &&
      resultByName.match(this.name) &&
      resultBySupplierId.toString().match(this.supplierId) &&
      resultByCategoryId.toString().match(this.categoryId) &&
      resultByQtyPerUnit.toString().match(this.quantityPerUnit) &&
      resultByUnitPrice.toString().match(this.unitPrice) &&
      resultByUnitsInStock.toString().match(this.unitsInStock) &&
      resultByUnitsOnOrder.toString().match(this.unitsOnOrder) &&
      resultByReorderLevel.toString().match(this.reorderLevel) &&
      resultByDisc.toString().match(this.discontinued)
    );
  });
},

标签: javascriptvue.jsvuejs2

解决方案


我想你应该将filteredResults函数重命名为getFilteredResultsfilteredResults作为数组添加到一个data部分,并在search函数中执行如下操作:

<result-item
  :data="filteredResults"
  :total-pages="Math.ceil(filteredResults.length / 10)"
  :total="filteredResults.length"
  :per-page="10"
  :current-page="currentPage"
  @pagechanged="onPageChange"
/>
...
methods: {
  search () {
    this.filteredResults = this.getFilteredResults()
  }
  reset () {
   // clear all fields here
   ...
   this.filteredResults = []
  }
}

推荐阅读