Bootstrap+Laravel:Ajax成功后无刷新添加数据至视图并复用功能
无刷新添加新Interest元素的实现方案
嘿,我来帮你搞定这个需求!既然控制器已经返回了新创建的interest数据,我们只需要在AJAX成功回调里把这个数据转换成对应的HTML结构,插入到现有列表中,同时处理好模态框和组件初始化就行。下面是具体的步骤:
第一步:准备可复用的HTML模板(让代码更整洁)
先在页面里加几个隐藏的模板,用来存单个interest卡片和对应的模态框结构,这样后面动态生成的时候直接替换变量就行,不用在JS里写一大串HTML:
<!-- 隐藏的Interest卡片模板 --> <div id="interest-card-template" style="display: none;"> <div class="col-md-4 col-sm-6 col-xs-12 mtm-10 mtmm-115"> <div class="box-icon box-icon-center box-icon-round box-icon-large text-center"> <div class="front rahmen_iboard box-shadow-7"> <div class="box1" style="background-color:#FFFFFF"> <div class="box-icon-title"> <div class="z-100"> <a class="dropdown-toggle" data-toggle="dropdown" href="#"> <i class="ico-xs glyphicon glyphicon-option-vertical float-right pt-8"></i> </a> <ul class="dropdown-menu dropdown-left-iboard dropdown-menu-right"> <li class="dropdown-item"> <a class="p-2" data-toggle="modal" data-target="#updateInterest__ID__"><i class="ico-xs glyphicon glyphicon-globe"></i> Bearbeiten</a> <a class="p-2" data-toggle="modal" data-target="#delteInterest__ID__"><i class="ico-xs fa fa-remove"></i> Löschen</a> </li> </ul> </div> <div class="img-ausschnitt"> <a class="img-hover" href="{{ route('interests.show', '__ID__') }}"> <img class="img-fluid" src="__IMAGE_SRC__" alt="" /> </a> </div> <div class="progress"> <div class="__PROGRESS_CLASS__ h-7" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width:__RATIO__%;"> </div> </div> <span class="mdl-badge" data-badge="2"><b> __NAME__</b></span> </div> </div> </div> </div> </div> </div> <!-- 更新模态框模板 --> <div id="update-modal-template" style="display: none;"> @include('modal.updateInterest', ['interest' => (object)['id' => '__ID__', 'name' => '__NAME__', 'itag' => '__ITAG__']]) </div> <!-- 删除模态框模板 --> <div id="delete-modal-template" style="display: none;"> @include('modal.delteInterest', ['interest' => (object)['id' => '__ID__', 'name' => '__NAME__']]) </div>
模板里的__ID__、__NAME__这些是占位符,后面用JS替换成实际数据。
第二步:修改AJAX的Success回调
现在要在AJAX请求成功后,把新的interest数据转换成HTML,插到页面里,还要添加对应的模态框,并且重新初始化Bootstrap组件,确保新元素的功能正常:
<script type="text/javascript"> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $("#storeinterest").click(function(e){ e.preventDefault(); var itag = $('#create_itag').val(); var name = $('#create_name').val(); $.ajax({ type:'POST', url:'{{ route('interests.store') }}', data:{name:name, itag:itag}, success:function(data){ // 原来的提示和模态框隐藏逻辑保留 _toastr_new(data.message, "top-full-width", "success", false, '.toastr-notify', 0); $('#create_itag').tagsinput('removeAll'); $('#create_name').val(''); $('#addInterest').delay(1000).fadeOut(450); setTimeout(function(){ $('#addInterest').modal("hide"); }, 1500); // --- 新增:动态添加新Interest到页面 --- const newInterest = data.interest; // 1. 生成Interest卡片的HTML let cardHtml = $('#interest-card-template').html(); // 替换基本占位符 cardHtml = cardHtml.replace(/__ID__/g, newInterest.id) .replace(/__NAME__/g, newInterest.name) .replace(/__RATIO__/g, newInterest.ratio); // 处理进度条样式 const progressClass = newInterest.ratio < 20 ? 'progress-bar-danger' : 'progress-bar-primary'; cardHtml = cardHtml.replace('__PROGRESS_CLASS__', progressClass); // 处理图片地址 let imageSrc = '{{ Storage::url('defaults/posts/nopost_interest.jpg') }}'; if (newInterest.mostVote && newInterest.mostVote.postsImages.length > 0) { const randomImg = newInterest.mostVote.postsImages[Math.floor(Math.random() * newInterest.mostVote.postsImages.length)]; imageSrc = '{{ Storage::url('') }}' + randomImg.image_thumbnail; } cardHtml = cardHtml.replace('__IMAGE_SRC__', imageSrc); // 把新卡片插到列表最前面(要插到最后面用append) $('.infinite-scroll .row').prepend(cardHtml); // 2. 生成并添加更新模态框 let updateModalHtml = $('#update-modal-template').html(); updateModalHtml = updateModalHtml.replace(/__ID__/g, newInterest.id) .replace(/__NAME__/g, newInterest.name) .replace(/__ITAG__/g, newInterest.itag); $('body').append(updateModalHtml); // 3. 生成并添加删除模态框 let deleteModalHtml = $('#delete-modal-template').html(); deleteModalHtml = deleteModalHtml.replace(/__ID__/g, newInterest.id) .replace(/__NAME__/g, newInterest.name); $('body').append(deleteModalHtml); // 4. 重新初始化Bootstrap组件,确保新元素的下拉、模态框能正常工作 $('.dropdown-toggle').dropdown(); $('[data-toggle="modal"]').modal({show: false}); // 初始化但不显示 } }); }); </script>
第三步:注意这些细节
- 特殊字符处理:如果Interest的名称包含引号或者特殊字符,记得在控制器返回数据的时候转义,或者在JS里用
encodeURIComponent处理,避免HTML结构被破坏。 - 事件委托:如果你的编辑、删除按钮有自定义的AJAX事件,要改成事件委托的方式绑定,比如:
// 用事件委托绑定删除按钮的点击事件,新元素也能触发 $('body').on('click', '[data-target^="#delteInterest"]', function() { // 这里写你的删除逻辑 }); - 模态框ID唯一性:模板里的
__ID__会被替换成新Interest的ID,确保每个模态框的ID都是唯一的,不会和现有模态框冲突。 - 分页兼容:如果你的列表有分页,新元素插在顶部是合理的,因为它是最新创建的,用户打开页面第一页就能看到。
这样操作后,新创建的Interest就会无刷新地出现在页面上,而且和现有元素一样,有下拉菜单、编辑删除模态框的全部功能!
内容的提问来源于stack exchange,提问作者slickness
相关产品推荐
相关产品推荐

