Nuxt对接Laravel分页接口实现客户端实时搜索过滤失效问题
问题根源
你当前的实现逻辑是后端通过paginate()仅返回单页数据,前端仅持有当前页的数据集,所以本地过滤只能作用于当前页内容,这是前后端分工逻辑未对齐导致的,并非代码语法错误。
解决方案
共有两种可选实现方式,可根据你的业务数据量选择:
方案1:服务端实现搜索逻辑(推荐,适配任意数据量)
这是性能最优、适用范围最广的方案,无需前端拉取全量数据,改动成本低:
- 前端监听搜索字段
search.domain的变化,每次变化后将搜索参数带入接口请求,同时将页码重置为1 - 后端Laravel接口接收搜索参数后,先执行模糊匹配筛选,再调用
paginate()返回筛选后的分页结果
代码改动示例
前端JS新增搜索监听、调整请求参数:
export default { // 原有代码不变 watch: { page (val) { this.navigateToPage(this.page) }, // 新增搜索词监听 'search.domain'() { this.page = 1 this.getDomains() } }, methods: { getDomains () { this.hasErrors = false // 拼接请求参数 const params = new URLSearchParams({ page: this.page, domain: this.search.domain }) this.$axios.get(`${process.env.API_URL}/api/domains?${params.toString()}`, { timeout: 60000 }).then(res => { // 原有处理逻辑不变 }) } } }
Laravel后端接口改造:
public function index(Request $request) { $query = Domain::query(); // 存在搜索参数时先执行模糊筛选 if ($request->filled('domain')) { $query->where('domain', 'like', "%{$request->input('domain')}%"); } // 筛选完成后再分页 $domains = $query->paginate(10); return response()->json([ 'success' => true, 'domains' => $domains ]); }
方案2:前端全量拉取后做本地分页+搜索(仅适合总数据量<1000条的场景)
如果不想改造后端,且业务数据量很小,可以一次性拉取全量数据到前端,再自行实现分页和搜索:
- 后端新增全量数据接口,或把原有接口的
paginate()改为get()返回所有记录 - 前端存储全量数据,先做搜索过滤,再对过滤后的结果手动分页
代码改动示例
前端JS调整逻辑:
export default { data () { return { // 原有变量不变 allDomains: [], // 存储全量域名数据 perPage: 10 // 自定义每页条数,和原分页规则保持一致 } }, created () { this.getAllDomains() // 初始化拉取全量数据 }, methods: { getAllDomains () { this.hasErrors = false this.$axios.get(`${process.env.API_URL}/api/domains/all`, { timeout: 60000 }).then(res => { if (res.data.success) { this.isLoading = false // 处理registrar字段格式 this.allDomains = res.data.domains.map(domain => { if (typeof domain.registrar == 'string' && domain.registrar != null) { domain.registrar = JSON.parse(domain.registrar) } return domain }) } }).catch(err => { this.isLoading = false this.hasErrors = true }) }, // 原有getDomains、navigateToPage方法可删除 }, computed: { // 第一步:对全量数据做搜索过滤 filteredDomains () { return this.allDomains.filter(domain => { return domain.domain.toLowerCase().includes(this.search.domain.toLowerCase()) }) }, // 第二步:对过滤后的结果做分页切割 paginatedDomains () { const start = (this.page - 1) * this.perPage return this.filteredDomains.slice(start, start + this.perPage) }, // 分页组件总条数替换为过滤后的总条数 filteredTotal () { return this.filteredDomains.length } }, watch: { // 搜索词变化时重置页码 'search.domain'() { this.page = 1 } } }
模板部分调整:
v-for遍历的对象从filteredDomains改为paginatedDomains- 分页组件的
total-rows属性从domains.total改为filteredTotal - 分页组件的
per-page属性改为perPage
你提到的循环拉取所有分页构造全量列表的方式完全没有必要,会增加不必要的请求开销,稳定性也差,优先选择以上两种方案即可。
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

