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 对结果进行分页