jQuery分页点击事件多次触发且数据加载缓慢如何解决
问题根因说明
- 事件多次触发原因
- 使用
$(document).on事件委托绑定点击事件,如果这段JS代码放在会被动态替换的页面内容中,每次分页加载后都会重复绑定事件,导致一次点击触发多次回调。 - 没有加请求锁,用户连续点击分页链接会发起多个重复请求。
- 原代码直接替换整个
<body>内容,会导致页面所有资源重新加载,同时内嵌的JS脚本重复执行,进一步加剧事件重复绑定的问题。
- 加载耗时长原因
- 接口返回整个页面的HTML,返回体积大,传输耗时久。
- 替换整个body导致页面所有静态资源(样式、脚本、图片)重新渲染加载,额外增加耗时。
解决方案
第一步:修改jQuery代码
增加请求锁、事件防重复绑定、只替换列表区域内容:
// 请求锁,避免重复发起请求 let isLoading = false; // 绑定事件前先解绑之前的同类型事件,彻底解决重复绑定问题 $(document).off('click', '.pagination a').on('click', '.pagination a', function(event) { event.preventDefault(); if (isLoading) return; isLoading = true; // 增加加载提示,避免用户重复点击 $('#table_data').html('<p style="text-align:center;padding:20px 0;">加载中...</p>'); const page = $(this).attr('href').split('page=')[1]; getData(page); }); function getData(page) { $.ajax({ url: "pagination?page=" + page, }).done(function(res) { // 仅替换列表区域内容,不修改页面其他部分 $('#table_data').html(res); }).fail(function() { $('#table_data').html('<p style="text-align:center;padding:20px 0;color:#f56c6c;">加载失败,请刷新重试</p>'); }).always(function() { // 请求结束后释放锁 isLoading = false; }); }
第二步:拆分Blade模板
将列表区域的代码单独抽成子模板,减少接口返回的内容体积:
- 新建
resources/views/posts/post_list.blade.php,内容如下:
@if(count($posts)>0) @foreach ($posts as $post) <div class="well" > <div class="row"> <div class="col-md-4 col-sm-4"> <!-- 增加图片懒加载,优化页面渲染速度 --> <img loading="lazy" style="height:300px; width:400px;" src="/storage/cover_images/{{$post->cover_image}}" alt="{{$post->title}}"> </div> <div class="col-md-8 col-sm-8"> <h3><a href="/posts/{{$post->id}}">{{$post->title}}</a></h3> <small>Written on {{$post->created_at}}</small> </div> </div> </div> @endforeach {{$posts->links()}} @else <p>No Post Found</p> @endif
- 修改
index.blade.php代码,修正原来的标签嵌套错误,引入子模板:
@extends('layouts.app') @section('content') <!-- 修正原代码h1开标签对应h3关标签的错误 --> <h1>Post</h1> <div id="table_data"> @include('posts.post_list') </div> @endsection
第三步:修改后端控制器逻辑
判断请求类型,AJAX请求只返回子模板内容:
use Illuminate\Http\Request; public function index(Request $request) { // 原有分页查询逻辑保持不变 $posts = \App\Models\Post::paginate(10); // 识别AJAX请求,仅返回列表部分的HTML if ($request->ajax()) { return view('posts.post_list', compact('posts'))->render(); } // 普通页面请求返回完整页面 return view('posts.index', compact('posts')); }
额外优化建议
- 可以给加载中的分页链接增加
disabled样式,进一步避免用户误点。 - 封面图片可以提前做压缩处理,减少图片加载耗时。
- 把jQuery绑定事件的代码放到
app.blade.php的底部,不要放在index.blade.php中,从根源避免重复加载执行。
内容的提问来源于stack exchange,提问作者Deku
相关产品推荐
相关产品推荐

