jQuery Form Repeater嵌套组件添加元素时触发外部重复器异常问题
兄弟,我帮你排查出嵌套repeater点内部Add却触发外部新增的问题了,主要是两个核心坑,咱们一步步填上:
问题根源
- 重复ID踩了HTML规范的雷:你的HTML里
m_repeater_3和m_repeater_2都重复出现了两次!ID在页面里必须是唯一的,jQuery用ID选元素时,虽然表面能跑,但会导致事件绑定和初始化逻辑彻底混乱,这是外部repeater被误触发的主要原因。 - 嵌套repeater初始化时机错了:页面加载时直接全局初始化所有内部repeater,但外部repeater新增的项里的内部repeater当时还没生成,而且全局绑定会让事件冒泡到外部容器,触发不该有的新增。
修复步骤
第一步:把重复ID换成唯一标识/类
先把HTML里重复的ID改掉,外部repeater用唯一ID,内部repeater因为每个外部项都会有一个,用class更合适。修改后的HTML大概是这样:
<!-- 外部Repeater:唯一ID --> <div id="outer_repeater"> <div class="form-group form-group-last row"> <div data-repeater-list="color" class="col-lg-10"> <div class="form-group row align-items-center"> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__label"> <label class="m-label m-label--single">Color:</label> </div> </div> </div> </div> <!-- 外部Repeater项 --> <div data-repeater-item class="form-group row align-items-center"> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__control"> <input type="text" class="form-control" name="color" placeholder="Color" required> </div> </div> </div> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__control"> <input type="file" class="form-control" name="image_4" required> </div> </div> </div> <div class="col-md-3"> <a href="javascript:;" data-repeater-delete class="btn-sm btn btn-danger btn-bold"> <i class="la la-trash-o"></i> </a> </div> <!-- 内部Repeater:用class代替重复ID --> <div class="inner_repeater"> <div class="form-group form-group-last row"> <div data-repeater-list="stock" class="col-lg-10"> <div class="form-group row align-items-center"> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__label"> <label class="m-label m-label--single">Size:</label> </div> </div> </div> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__label"> <label class="m-label m-label--single">Stock:</label> </div> </div> </div> </div> <!-- 内部Repeater项 --> <div data-repeater-item class="form-group row align-items-center"> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__control"> <input type="text" class="form-control" name="Size" placeholder="Size" required> </div> </div> </div> <div class="col-md-3"> <div class="m-form__group--inline"> <div class="m-form__control"> <input type="text" class="form-control" name="stock" placeholder="Stock" required> </div> </div> </div> <div class="col-md-3"> <a href="javascript:;" data-repeater-delete class="btn-sm btn btn-danger btn-bold"> <i class="la la-trash-o"></i> </a> </div> </div> </div> </div> <div class="form-group form-group-last row"> <label class="col-lg-2 col-form-label"></label> <div class="col-lg-4"> <a href="javascript:;" data-repeater-create class="btn btn-bold btn-sm btn-brand"> <i class="la la-plus"></i> Add Size/Stock </a> </div> </div> </div> </div> </div> </div> <div class="form-group form-group-last row"> <label class="col-lg-2 col-form-label"></label> <div class="col-lg-4"> <a href="javascript:;" data-repeater-create class="btn btn-bold btn-sm btn-brand"> <i class="la la-plus"></i> Add Color </a> </div> </div> </div>
第二步:调整JS初始化逻辑,支持动态嵌套
外部repeater新增的项里的内部repeater是动态生成的,所以得在外部项显示的时候,单独初始化里面的内部repeater,而不是页面加载时全局绑定。修改后的JS代码:
var FormRepeater = function() { // 封装初始化单个内部Repeater的函数 var initInnerRepeater = function($container) { $container.repeater({ initEmpty: false, defaultValues: { 'code': '' }, show: function() { $(this).slideDown("slow"); }, hide: function(deleteElement) { $(this).slideUp(deleteElement); } }); }; // 初始化外部Repeater var initOuterRepeater = function() { $('#outer_repeater').repeater({ initEmpty: false, defaultValues: { 'code': '' }, show: function() { // 外部项显示时,初始化它里面的内部Repeater var $innerRepeater = $(this).find('.inner_repeater'); initInnerRepeater($innerRepeater); // 再执行展开动画 $(this).slideDown("slow"); }, hide: function(deleteElement) { $(this).slideUp(deleteElement); } }); }; return { init: function() { // 先初始化页面已有的内部Repeater initInnerRepeater($('.inner_repeater')); // 再初始化外部Repeater initOuterRepeater(); } }; }(); // 页面加载完成后执行初始化 $(document).ready(function() { FormRepeater.init(); });
为啥这样就能解决?
- 唯一标识避免混乱:用唯一ID绑定外部repeater,class绑定内部repeater,彻底解决了ID重复导致的选择器错误,确保每个按钮的事件只绑定到对应的repeater容器。
- 动态初始化适配嵌套:外部项新增时才初始化里面的内部repeater,既保证了动态生成的内部repeater能正常工作,又避免了事件冒泡到外部容器触发误操作。
内容的提问来源于stack exchange,提问作者Rishikesh Singh
相关产品推荐
相关产品推荐

