如何让jquery.each函数与动态元素的.on('change')函数一起工作

How do I get jquery .each function working with a .on('change') function for dynamic elements

本文关键字:函数 change 工作 一起 on jquery each 元素 动态      更新时间:2023-09-26

我在页面中有一个库,您可以在其中单击加号和减号来添加和删除库项目,然后将文件添加到新添加项目的输入中。

我创建了一个文件读取器来获取文件url,但它只适用于该页面上的第一个元素,之后动态添加的任何内容都不受影响。

这是我的JS:

$('#gallery .gallery-item .file_upload').each(function() {
    var $this = $( this );
    //$('body').on('click', 'input', function() {
    $this.on( 'change', 'input', function(evt){
        var files = evt.target.files;
        var file = files[0];
        console.log(files[0]);
        var reader = new FileReader();
        reader.onload = (function(file) {
            return function(e) {
                console.log(e.target.result);
            };
        })(file);
        reader.readAsDataURL(file);
    });
  });

附加库项功能:

$('#gallery')
    .on('cocoon:before-insert', function(e,image_field) {
        image_field.insertAfter( $(this).next() );
    })
    .on('cocoon:after-remove', function(e, image_field) {
        $(this).data('remove-timeout', 1000);
        image_field.fadeOut('slow');
});
    $('.gallery-item').each(function() {
        $(this).next('a.add_fields').appendTo(this);
        $(this).next('input').appendTo(this);
    });

HTML:

<div class="image-field">
            <div class="file_upload">
                <input class="image_file" id="gallery_files" name="book[gallery_attributes][images_attributes][1412768497650][file]" type="file">
            </div>
        </div>

有人能告诉我为什么.each函数不能与附加的新项的.on函数一起使用吗。我认为这是最重要的功能,显然在这里不起作用,下面的其他功能也不起作用。

您已经正确地确定需要使用事件委派,因为您已经在页面上动态添加了元素。问题是,事件委派对代码运行时存在的元素有效,并且您正在使用.each()循环来迭代一个集合,该集合希望包含动态添加的元素(它不会,因为它们当前不存在)。

本质上,问题在于初始选择器$('#gallery .gallery-item .file_upload')

该选择器的.gallery-item .file_upload部分是标识事件委派的动态元素的部分,因此您需要使用类似于以下内容的内容:

$('#gallery').on('change', '.gallery-item .file_upload input', function(e) {
    // your code here
});

我取消了对.each()的呼叫,因为它是多余的;.on()已经在一组匹配的元素上迭代,而$('#gallery')选择器无论如何都应该只匹配一个元素。

注意:您在选择器中使用了.gallery-item,但在您提供的HTML中只有一个image-field类。这可能是个问题,也可能不是个问题,这取决于页面的确切外观,因为你还没有提供我不得不猜测的信息。

为什么还要使用.each()?您所需要的只是使用选择器,因为jQuery已经将所有选定的项目循环到.on()

$('#gallery .gallery-item .file_upload').on( 'change', 'input', function(evt){
        var files = evt.target.files;
        var file = files[0];
        console.log(files[0]);
        var reader = new FileReader();
        reader.onload = (function(file) {
            return function(e) {
                console.log(e.target.result);
            };
        })(file);
        reader.readAsDataURL(file);
});

问题是,每个处理程序都从库中获取当前存在的输入,除非每次添加新项时都进行循环,但随后会在同一元素上多次绑定处理程序。