You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:09:07