Vue JS 对分页 Laravel 结果的实时客户端搜索过滤器

Posted

技术标签:

【中文标题】Vue JS 对分页 Laravel 结果的实时客户端搜索过滤器【英文标题】:Vue JS real-time client search filter on paginated Laravel results 【发布时间】: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 循环来构造所有域的列表并过滤此列表?不过,这似乎有点矫枉过正......

【问题讨论】:

【参考方案1】:

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

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

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

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

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

【讨论】:

谢谢你,这有助于我验证我的方向!

以上是关于Vue JS 对分页 Laravel 结果的实时客户端搜索过滤器的主要内容,如果未能解决你的问题,请参考以下文章

使用 Vue.Js / Inertia.js 和 Laravel 对结果进行分页

laravel5.5中添加对分页样式的修改上一页和下一页

Laravel:分页()的结果在页面之间是不稳定的

Laravel Vue Js 分页

javascript Laravel和Vue js app的分页

使用 laravel5.2 、 vue.js 和 pusher 实时获取数据