【问题标题】:Vue JS real-time client search filter on paginated Laravel resultsVue JS 对分页 Laravel 结果的实时客户端搜索过滤器
【发布时间】:2021-08-31 15:01:08
【问题描述】:

我在向我的 Nuxt JS 项目添加客户端实时搜索过滤时遇到了一些麻烦,该项目从我的 Laravel 8 API 中提取数据。我的 Laravel 8 API 使用 paginate() 方法对我的数据库中的结果进行分页并返回一些 JSON,其中 data 数组包含当前页面的所有记录。

我的前端包含一个带有v-for 的表格,循环遍历filteredDomains 提供的一些过滤结果,这实际上是在对我的API 的请求获得结果后获取数据。

问题是,我在前端的实时搜索有效,但只针对第一页,我想让它过滤和搜索所有页面,就好像它们是一页一样 (以前是这样的,以前也这样,现在分页了)

我错过了什么?

<b-row>
  <b-col>
    <b-form-input
      style="padding-right: 10rem;"
      v-model="search.domain"
      type="text"
      size="lg"
      maxlength="256"
      placeholder="Start typing a domain...">
    </b-form-input>
  </b-col>
</b-row>
<b-row>
  <b-col>
    <div class="table-responsive">
      <table class="table table-bordered table-striped">
        <thead>
          <tr>
            <th scope="col"></th>
            <th scope="col">Domain</th>
            <th scope="col">Registrar</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(domain, index) in filteredDomains" :key="index" class="domain-row">
            <td class="text-center" style="min-width: 60px;">
              ...
            </td>
            <td :style="domain.has_valid_ssl == 1 ? 'min-width: 260px;' : 'min-width: 150px;'">
              ...
            </td>
            <td style="min-width: 150px;">
              ...
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </b-col>
</b-row>
<b-row>
  <b-col>
    <b-pagination
      v-model="page"
      :total-rows="domains.total"
      :per-page="domains.per_page"
      first-number
      last-number
      pills
    ></b-pagination>
  </b-col>
</b-row>

我的脚本是:

export default {
  data () {
    return {
      page: this.$route.query.page ? this.$route.query.page : 1,
      hasErrors: false,
      isLoading: true,
      search: {
        domain: ''
      },
      domains: []
    }
  },
  created () {
    this.getDomains()
  },
  methods: {

    /*
    ** Get domains
    */
    getDomains () {
      this.hasErrors = false

      this.$axios.get(`${process.env.API_URL}/api/domains?page=${this.page}`, { timeout: 60000 }).then(res => {
        if (res.data.success) {
          this.isLoading = false
          this.hasErrors = false

          const domains = res.data.domains.data.length > 0 ? res.data.domains : []
          if (domains.data && domains.data.length > 0) {
            for (const [index, domain] of domains.data.entries()) {
              if (typeof domain.registrar != 'string' || domain.registrar == null) continue
              domain.registrar = JSON.parse(domain.registrar)
            }
          }

          this.domains = domains
        }
      }).catch(err => {
        this.isLoading = false
        this.hasErrors = true
      })
    }

    /*
    ** Navigate to a page
    */
    navigateToPage (page) {
      try {
        const goTo = page

        this.page = parseInt(goTo)
        this.$router.push({
          query: {
            page: this.page
          }
        })

        this.getDomains()
      } catch (err) {}
    }

  },
  computed: {

    /*
    ** Filter domains for searchable domains
    */
    filteredDomains () {
      if (!this.domains.data) {
        return []
      }
      return this.domains.data.filter(domain => {
        return domain.domain.toLowerCase().includes(this.search.domain.toLowerCase())
      })
    }

  },
  watch: {
    page (val) {
      this.navigateToPage(this.page)
    }
  }
}

也许我需要在我的filteredDomains 函数中执行for 循环来构造所有域的列表并过滤此列表?不过,这似乎有点矫枉过正......

【问题讨论】:

    标签: php laravel vue.js nuxt.js


    【解决方案1】:

    按照您当前使用分页的方式,您的数据中只有一页从 API 返回的域。默认情况下,这将是第一页,因此您的代码会按预期运行。

    要解决这个问题,我看到了两个选项:

    1. 获取所有域并过滤它们(如您自己建议的那样)。如果您想保留该功能,也可以在客户端实现分页。
    2. 将您的搜索词传递给您的 API。这样就需要在服务器端进行过滤,并且只返回过滤后的域。

    哪个更适合您的情况取决于项目的数量。如果项目相对较少,我会建议第一个选项,因为它将所有逻辑都保存在一个地方。但是,如果有数百甚至数千个项目,我会建议第二个选项,因为数据库通常可以更好地进行这种过滤。

    在任何一种情况下,您都应该考虑添加去抖动以帮助提高性能。在用户在搜索框中键入每个字母后,您的数据将被一遍又一遍地搜索。使用去抖动功能,只有在用户停止输入一段指定的时间(通常大约 300 毫秒)后,数据才会被过滤。

    【讨论】:

    • 谢谢你,这有助于我验证我的方向!
    猜你喜欢
    • 1970-01-01
    • 2017-02-24
    • 2018-06-22
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2021-05-14
    • 2021-07-29
    • 2021-11-08
    相关资源
    最近更新 更多