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

jQuery克隆Select2输入框后新组件无响应,求排查方案

问题描述

我用jQuery的clone()和append()方法实现了包含Select2输入框的表单行添加功能,但点击“Add More”按钮生成新表单行后,新的Select2组件无法正常响应交互。请问我遗漏了什么关键步骤?


HTML代码

<div class="row">
  <div class="col-md-12 service-group">
        <div class="row">
            <div class="form-group mb-3 col-md-6">
                <label class="form-label">Service</label>
                <div>
                    <select type="text" class="form-select service-select" placeholder="Services" value="" name="items[0][service]" id="service-0" required>
                        <option value="" disabled selected>Select your option</option>
                        @foreach ($services as $service)
                            <option value="{{$service->service_name}}"  data-id="{{$service->amount}}">{{$service->service_name}}</option>
                        @endforeach
                    </select>
                </div>
            </div>

            <div class="form-group mb-3 col-md-6">
                <label class="form-label">Amount</label>
                <div>
                    <input type="text" class="form-control" name="items[0][amount]" id="amount-0" placeholder="Amount"  required>
                </div>
            </div>
            <div class="form-group mb-3 col-md-12">
                <label class="form-label">Description</label>
                <textarea class="form-control" id="description-0" name="items[0][description]" rows="6" placeholder="Description.." required></textarea>
            </div>
        </div>
    </div>
</div>

<div class="more-service-box"></div>

<div class="col-md-12">
    <button type="button" id="addmore" class="btn btn-default">
        <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-plus" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
            <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
            <circle cx="12" cy="12" r="9"></circle>
            <line x1="9" y1="12" x2="15" y2="12"></line>
            <line x1="12" y1="9" x2="12" y2="15"></line>
        </svg> Add More
    </button>
    <button type="button" id="remove" class="btn btn-default">
        <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-minus" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
            <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
            <circle cx="12" cy="12" r="9"></circle>
            <line x1="9" y1="12" x2="15" y2="12"></line>
        </svg> Remove
    </button>
</div>

JavaScript代码

$(".service-select").select2({
  placeholder: "Select a programming language",
  allowClear: true
});

// Add Service , Amount, Description
$('#addmore').click(function () {
    var index = $('.service-group').length;
    
    var $service = $('.service-group:first').clone();

    $service.find('select[name*=service]')
        .val('')
        .attr('name', 'items[' + index + '][service]')
        .attr('id', 'service-' + index);

    $service.find('input[name*=amount]')
        .val('')
        .attr('name', 'items[' + index + '][amount]')
        .attr('id', 'amount-' + index);

    $service.find('textarea[name*=description]')
        .val('')
        .attr('name', 'items[' + index + '][description]')
        .attr('id', 'description-' + index);

    $service.appendTo('.more-service-box');

    $("body").on("change", "select[id=service-"+ index +"]", function() {
        var amount = $(this).find("option:selected").data("id");
        $(this).closest(".service-group").find("input[id=amount-"+ index +"]").val(amount)
    })
});

$("body").on("change", "select[id=service-0]", function() {
    var amount = $(this).find("option:selected").data("id");
    $(this).closest(".service-group").find("input[id=amount-0]").val(amount)
});

$("#remove").on("click", function() {  
    $(".more-service-box").children().last().remove();  
});  

问题原因与解决方法

核心问题是:你克隆的是已经初始化完成的Select2元素,它包含了Select2生成的额外DOM结构和绑定的私有事件,但这些克隆内容无法成为有效的Select2实例,自然无法交互。需要按以下步骤修正:

关键修正点

  1. 克隆前先销毁原行的Select2:把原行的Select2还原成原生<select>,确保克隆的是干净的基础元素
  2. 克隆后恢复原行的Select2:保证原行功能不受影响
  3. 新行添加后重新初始化Select2:让新的<select>成为可交互的Select2实例
  4. 优化事件绑定:用类选择器做事件委托,不用为每行单独绑定

修正后的JavaScript代码

// 初始化第一行的Select2
$(".service-select").select2({
  placeholder: "Select a programming language",
  allowClear: true
});

// 统一绑定service选择事件,无需为每行单独写逻辑
$("body").on("change", ".service-select", function() {
  var amount = $(this).find("option:selected").data("id");
  $(this).closest(".service-group").find("input[name*=amount]").val(amount);
});

// Add Service , Amount, Description
$('#addmore').click(function () {
  var index = $('.service-group').length;
  var $originalGroup = $('.service-group:first');

  // 1. 先销毁原行的Select2,还原成原生select
  $originalGroup.find('.service-select').select2('destroy');
  
  // 2. 克隆干净的原生表单行
  var $service = $originalGroup.clone();
  
  // 3. 恢复原行的Select2初始化
  $originalGroup.find('.service-select').select2({
    placeholder: "Select a programming language",
    allowClear: true
  });

  // 修改新行的表单元素属性
  $service.find('select[name*=service]')
    .val('')
    .attr('name', 'items[' + index + '][service]')
    .attr('id', 'service-' + index);

  $service.find('input[name*=amount]')
    .val('')
    .attr('name', 'items[' + index + '][amount]')
    .attr('id', 'amount-' + index);

  $service.find('textarea[name*=description]')
    .val('')
    .attr('name', 'items[' + index + '][description]')
    .attr('id', 'description-' + index);

  // 添加到DOM
  $service.appendTo('.more-service-box');

  // 4. 初始化新行的Select2
  $service.find('.service-select').select2({
    placeholder: "Select a programming language",
    allowClear: true
  });
});

$("#remove").on("click", function() {  
  var $lastGroup = $(".more-service-box").children().last();
  // 移除前销毁Select2,避免内存泄漏
  $lastGroup.find('.service-select').select2('destroy');
  $lastGroup.remove();  
});

内容的提问来源于stack exchange,提问作者devsam247

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:55:29