Почему список выбранных файлов всегда пуст, если я получаю список файлов перед изменением?

Я хочу показать имена файлов после их выбора. Итак, почему список файлов в обработчике onchange пуст?

Вот мой код:

window.onload = function () {
    let list = document.getElementById("demo");
    let files = document.getElementById("addFileId").files;

    document.getElementById("addFileId").onchange = function () {
        console.info(files);
        console.info(files[0]);

        for (let i = 0; i < files.length; i++) {
            let li = document.createElement('li');
            li.innerText = files[i].name;
            list.appendChild(li);
        }
    };
};
<input type = "file" multiple class = "form-control"
    name = "file" id = "addFileId" required>

<ul id = "demo"></ul>

Поместите свой let files = внутри вашего мероприятия, иначе вы запросите файлы до того, как вы их выбрали.

Keith 16.03.2022 13:21

На самом деле это не так. Свойство files всегда относится к одному и тому же FileList. Выбор файлов изменяет этот список, поэтому размещение let files =; внутри слушателя не имеет значения. @Enesan Код уже работает нормально.

Sebastian Simon 16.03.2022 13:25

@SebastianSimon Я получаю undefined выбор файла, не перемещая эту строку, я использую Chrome, какой браузер вы используете?

Keith 16.03.2022 13:28

@SebastianSimon Только что попробовал в Firefox, и он сохраняет тот же экземпляр, поэтому похоже, что Chrome создает новый экземпляр, поэтому, возможно, лучше всего, чтобы OP делал то, что я сказал, и не предполагайте, что FileList всегда один и тот же экземпляр ..

Keith 16.03.2022 13:34

@Keith Firefox Nightly 100.0a1. Хорошо, я только что проверил в Chrome, и есть разница. Думаю, я знаю, почему существует эта несовместимость: Технические характеристики не определяет ни [SameObject], ни [NewObject] для атрибута files IDL. Он также не объявляет это как readonly. Таким образом, не указано, должно ли files === document.getElementById("addFileId").files быть true или false. Похоже, в спецификации DOM есть проблема с GitHub, о которой нужно сообщить…

Sebastian Simon 16.03.2022 13:35

@SebastianSimon Престижность за проверку спецификации, приятно знать ..

Keith 16.03.2022 13:37

@SebastianSimon, да, я только что попробовал в Firefox, это действительно работает (: спасибо за эту информацию

Enesan 16.03.2022 13:48

Копнем немного дальше, filesиспользовал будет только для чтения, но был желание установить свойство files в другой экземпляр FileList. Расширение атрибута [Тот же объект]Только применяется к атрибутам только для чтения, а расширение [НовыйОбъект]Только применяется к методам. Таким образом, filesдобытчик (где также существует установщик files) не может иметь расширение ни одного атрибута.

Sebastian Simon 16.03.2022 15:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
8
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема заключается в том, что объект списка файлов получен до, и срабатывает событие изменения. К моменту, когда событие действительно происходит, информация в списке уже устарела, а браузер уже прикрепил к узлу DOM новый список файлов. Решение состоит в том, чтобы получить список файлов внутри обработчиком события:

window.onload = function () {
    let list = document.getElementById("demo");
    let addFileId = document.getElementById("addFileId");
    
    addFileId.onchange = function () {
        let files = addFileId.files;
        console.info(files);
        console.info(files[0]);

        for (let i = 0; i < files.length; i++) {
            let li = document.createElement('li');
            li.innerText = files[i].name;
            list.appendChild(li);
        }
    };
};

Замечу, однако, что забавно, что образец спрашивающего прекрасно работает без изменений в Firefox 91 ESR, и комментаторы говорят, что он действует так же и в более новых версиях. По-видимому, Firefox вместо создания нового списка обновляет существующий объект списка файлов. Хром ведет себя так, как описано в вопросе; Я не тестировал браузер на основе WebKit, но думаю, что он работает как последний. По состоянию на 16 марта 2022 г. Спецификация HTML говорит, что при изменении выбора файла браузер должен

Update element's selected files so that it represents the user's selection.

что можно интерпретировать как угодно. Так что, вероятно, лучше не полагаться на какое-либо поведение.

So it is probably best not to rely on either behaviour. Не уверен, что вы имеете в виду, вы, конечно, можете полагаться на то, что список является новым экземпляром или существующим. Просто нельзя полагаться на то, что тот же самый экземпляр мутировал.
Keith 16.03.2022 14:30

О, спец. на самом деле говорит «При получении [атрибута files IDL] он должен вернуть объект FileList, который представляет текущие выбранные файлы. Этот же объект должен быть возвращен до тех пор, пока не изменится список выбранных файлов.» (выделено мной). Это все еще можно интерпретировать в любом случае, но я думаю, что здесь могло подразумеваться изменение ссылки…

Sebastian Simon 16.03.2022 16:36

Другие вопросы по теме