如何在元素属性更改时使用 JQuery 事件委托?

How to use JQuery event delegation on element attribute change?

我有一个带有编辑现有记录按钮的表单。单击按钮时,将打开一个模式以更新记录,包括一个用于删除附加到记录的现有文件的按钮,单击该按钮会触发对 delete_file PHP 脚本的 ajax 调用。如果文件存在,其文件名将在 'p' 元素中预览。

我 运行 遇到的问题是,如果用户编辑了一条不包含文件的记录,上传了一个文件,然后在不保存记录的情况下将其删除,我现有的代码不会无法删除文件。这是因为 HTML 是在文件上传时动态生成的,用于将文件 url 放在按钮属性中,该属性无法传递给文件删除。

经过研究,我认为解决方案是事件委托。我尝试了一些建议,但 none 奏效了。我怎样才能:

  1. 添加一个文件(文件名在 "$("button").attr("data-fileurl") // 这个有效
  2. 单击 'delete file' 按钮后,将 $("button").attr("data-fileurl") 存储在变量中
  3. 将 url 变量传递给 delete_file 函数

HTML:

<div id='file_upload' class='file-upload'>
  <input type='file' id='file_input' style='opacity:0;' />
  <p class='file_upload_text'>Click to upload file</p>
</div>
<div id='file_upload_preview' class='file-upload file-preview' style='display:none;'>
  <div class='file_preview'></div>
  <button id='fileurl' data-fileurl='' class='file_delete'>Delete</button>
</div>

JQuery:

jQuery(document).ready(function($) {
  var filesToUpload = [];
  var fileUrlDelegated = ""; 
  $('#file_input').on('change', function(e) {
    var files = e.target.files[0];
    filesToUpload.push(files);
    prepareUpload(filesToUpload);  
  $(".file_delete").on('click', function(e) {
    e.preventDefault();
    $(document.body).on('change', "button [data-fileurl]", function (event) { // not working
      fileUrlDelegated = $(event.target).attr("data-fileurl");
    });
    delete_file(fileUrlDelegated);
  });
});
      
function prepareUpload(file) { // upload file; dynamic HTML generated after an ajax call; this works
  var parent = $("#file_input").parent();
  var previewID = parent.attr("id") + "_preview";
  var previewParent = $("#"+previewID);
  previewParent.show();
  previewParent.children(".file_preview").empty().append( preview );
  previewParent.children( "button" ).attr("data-fileurl", data.url );
  parent.children("input").val("");
  parent.hide();
}
    
function delete_file (file_url) {  // works as long as url is provided
  $(".file_preview").text("");
  $("button").attr("data-fileurl", "");
  $("#file_upload_preview").hide();
  $("#file_upload").show();
  var data = new FormData();
  data.append("fileurl", file_url);
  $.ajax({
    url: general_globals.ajaxurl,
    type: 'POST',
    data: data,
    processData: false,
    contentType: false,
    cache: false,
    dataType: 'json'
  });
}

尝试使用 FileReader API 而不是依赖 AJAX 调用。你可以做一个像

这样的方法
function readURL() {
  var input = grab your input here;
  if (input.files && input.files[0]) {
    var reader = new FileReader();
    reader.onload = function(e) {
      $('#preview').attr('src', e.target.result);
     }
     reader.readAsDataURL(input.files[0]);
   }
};

这样,在用户保存记录之前你不会触及你的数据库,所以你的问题就解决了。

你只需要重写你的逻辑,code 的其余部分看起来很好。到 delete 文件并传递 data-fileurl - 您可以简单地检查文件 URL 是否存在,它是由 prepare Upload.

生成的

此外,要获取数据属性,我们可以简单地使用 .data 方法并在 jQuery 中写入 .data('fileurl') 以获取按钮 fileurl 然后将其传递给我们删除 functionajax 调用 backend.

为了获得正确的 fileURL我们可以在我们的删除函数中使用$(this)它指的是我们点击的元素将是.file_delete

为了安全起见,我们将在您的案例中使用 event Delegation,因为 HTML 是动态创建的。

将您的删除文件功能替换为:(代码在本地主机上测试并正常工作)

//Delete file
$(document).on('click', '.file_delete', function(e) {
  e.preventDefault();
  //Get the file URL
  var fileURL = $(this).data('fileurl')
  //Check if file URL exist - then call delete else do not anything
  if (fileURL != '') {
    //Call delete function
    delete_file(fileURL);
  } else {
    return false
  }
});