添加多个文件而不刷新当前文件的解决方法 (HTML, JS)

Workaround for adding multiple files without refreshing the current ones (HTML, JS)

我有一个简单的 <input>,它将 multiple files 作为上传。 问题如下:对于每个 file 上传(在我的例子中是图像),我还添加了一个 <select> tag 来为该图像选择宽度和高度,例如我 select 首先是 5 张图片,然后从 <select> option 中选择它们的 width x height 我想添加另一张图片,问题来了,添加另一张图片后,<select> tag options values 刷新回 default value 之前添加的每张图片。

这是我处理上传和预览的代码片段:

function loadFiles(event) {
    let imagesSection = document.getElementById("images-section");
    
    for (let i = 0; i < event.files.length; i++) {
        let image = new Image();
        image.src = URL.createObjectURL(event.files[i]);

        imagesSection.innerHTML += 
        "<div class=\"image-frame\">" +
            "<img src=\"" + image.src + "\">" +
            "<select id=\"image-options-" + i + "\" name=\"size\" id=\"image-size\" required>" +
                "<option value=\"\" selected disabled hidden>select size</option>" +
                "<option value=\"\" disabled>horizontal</option>" +
                "<option value=\"w10h15\">10cm x 15cm</option>" +
                "<option value=\"w13h15\">13cm x 18cm</option>" +
                "<option value=\"w20h15\">20cm x 25cm</option>" +
                "<option value=\"w20h15\">20cm x 30cm</option>" +
                "<option value=\"\" disabled>vertical</option>" +
                "<option value=\"w15h10\">15cm x 10cm</option>" +
                "<option value=\"w18h13\">18cm x 13cm</option>" +
                "<option value=\"w25h20\">25cm x 20cm</option>" +
                "<option value=\"w30h20\">30cm x 20cm</option>" +
            "</select>" +
        "</div>";
        //console.log(event.files[i]);
    }
};
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
        <link rel="stylesheet" href="root.css">
        <title>Images</title>
    </head>

    <body>
        <div class="container">
            <div class="print-section">
                <div id="images-section" class="images-section"></div>
                
                <div class="upload-section">
                    <input id="files-input" type="file" name="files" accept="image/*" multiple onchange="loadFiles(this)" value="" />
                </div>
            </div>
        </div>
    </body>
</html>

有没有办法在不重新上传以前的文件的情况下进行新的上传,从而保存 width x height?如果不是,我最好的猜测是尝试添加一个数组来保存选项值,然后在另一次上传后将它们恭敬地添加到每个图像中。

这就是您不应该使用 imagesSection.innerHTML += 的原因之一。

这里发生的是当前 DOM 被转换为 HTML,然后与您要添加的字符串连接并再次解析为 DOM。在那一步中,DOM 中表示为状态的所有内容都将丢失,例如输入元素的值、事件侦听器……。

  • new Image 已经创建了一个 ImageElement 可以添加到 DOM.

  • 使用createElementappendChild

  • 你也应该避免使用 onchange="loadFiles(this)" 而使用 addEventListener

  • 您的 select 有两个 id,并且 id 必须是唯一的,使用 i od 循环不会产生唯一的 id.

function createSizeSelectElement(id) {
    let select = document.createElement('select')
    // name should be unique for a form
    select.name = "size"

    // you have id twice and id has to be unique
    // select.id = "image-options-" + id
    // select.id = "image-size"
    select.required = true

    // here you should consider using a loop and appendChild too
    select.innerHTML =
      "<option value=\"\" selected disabled hidden>select size</option>" +
      "<option value=\"\" disabled>horizontal</option>" +
      "<option value=\"w10h15\">10cm x 15cm</option>" +
      "<option value=\"w13h15\">13cm x 18cm</option>" +
      "<option value=\"w20h15\">20cm x 25cm</option>" +
      "<option value=\"w20h15\">20cm x 30cm</option>" +
      "<option value=\"\" disabled>vertical</option>" +
      "<option value=\"w15h10\">15cm x 10cm</option>" +
      "<option value=\"w18h13\">18cm x 13cm</option>" +
      "<option value=\"w25h20\">25cm x 20cm</option>" +
      "<option value=\"w30h20\">30cm x 20cm</option>"
    return select
}

function loadFiles(event) {
  let imagesSection = document.getElementById("images-section");

  for (let i = 0; i < event.target.files.length; i++) {
    let image = new Image();
    image.src = URL.createObjectURL( event.target.files[i]);

    let info = document.createElement('div')
    info.classList.add('image-frame')

    info.appendChild(image)
    info.appendChild(createSizeSelectElement(i))
    
    imagesSection.appendChild(info)
  }
}

document.getElementById('files-input').addEventListener('change',loadFiles)
<div class="container">
  <div class="print-section">
    <div id="images-section" class="images-section"></div>

    <div class="upload-section">
      <input id="files-input" type="file" name="files" accept="image/*" multiple value="" />
    </div>
  </div>
</div>