Я хочу показать имена файлов после их выбора. Итак, почему список файлов в обработчике 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>
На самом деле это не так. Свойство files
всегда относится к одному и тому же FileList
. Выбор файлов изменяет этот список, поэтому размещение let files =
…;
внутри слушателя не имеет значения. @Enesan Код уже работает нормально.
@SebastianSimon Я получаю undefined
выбор файла, не перемещая эту строку, я использую Chrome, какой браузер вы используете?
@SebastianSimon Только что попробовал в Firefox, и он сохраняет тот же экземпляр, поэтому похоже, что Chrome создает новый экземпляр, поэтому, возможно, лучше всего, чтобы OP делал то, что я сказал, и не предполагайте, что FileList всегда один и тот же экземпляр ..
@Keith Firefox Nightly 100.0a1. Хорошо, я только что проверил в Chrome, и есть разница. Думаю, я знаю, почему существует эта несовместимость: Технические характеристики не определяет ни [SameObject], ни [NewObject] для атрибута files
IDL. Он также не объявляет это как readonly
. Таким образом, не указано, должно ли files === document.getElementById("addFileId").files
быть true
или false
. Похоже, в спецификации DOM есть проблема с GitHub, о которой нужно сообщить…
@SebastianSimon Престижность за проверку спецификации, приятно знать ..
@SebastianSimon, да, я только что попробовал в Firefox, это действительно работает (: спасибо за эту информацию
Копнем немного дальше, files
использовал будет только для чтения, но был желание установить свойство files
в другой экземпляр FileList
. Расширение атрибута [Тот же объект]Только применяется к атрибутам только для чтения, а расширение [НовыйОбъект]Только применяется к методам. Таким образом, files
добытчик (где также существует установщик files
) не может иметь расширение ни одного атрибута.
Проблема заключается в том, что объект списка файлов получен до, и срабатывает событие изменения. К моменту, когда событие действительно происходит, информация в списке уже устарела, а браузер уже прикрепил к узлу 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.
Не уверен, что вы имеете в виду, вы, конечно, можете полагаться на то, что список является новым экземпляром или существующим. Просто нельзя полагаться на то, что тот же самый экземпляр мутировал.
О, спец. на самом деле говорит «При получении [атрибута files
IDL] он должен вернуть объект FileList
, который представляет текущие выбранные файлы. Этот же объект должен быть возвращен до тех пор, пока не изменится список выбранных файлов.» (выделено мной). Это все еще можно интерпретировать в любом случае, но я думаю, что здесь могло подразумеваться изменение ссылки…
Поместите свой
let files =
внутри вашего мероприятия, иначе вы запросите файлы до того, как вы их выбрали.