#javascript #closures #dom-events #internet-explorer-11
Вопрос:
Итак, у меня есть страница, на которой в HTML есть одна кнопка загрузки. При загрузке страницы я вызываю приведенную ниже функцию, чтобы прикрепить прослушиватель событий изменений ко всем кнопкам загрузки:
// FileUpload JS
export function registerFileUploadEvents() {
const fileUploadElements = document.querySelectorAll('.file-upload')
Array.prototype.forEach.call(fileUploadElements, (fileUploadElement) => {
const fileInput = fileUploadElement.querySelector('input[type="file"]')
fileInput.addEventListener('change', e => {
const selectedFile = e.target.files[0]
if (selectedFile) {
e.target.closest('.file-upload').querySelector('.file-upload__filename').innerHTML = selectedFile.name // show uploaded file's name inside fileupload component
}
})
})
}
// Main JS
import 'registerFileUploadEvents' from './FileUpload.js'
registerFileUploadEvents()
После этого пользователь может добавить новую кнопку загрузки файлов, чтобы загрузить другой файл (не спрашивайте меня, почему они не позволяют пользователю загружать несколько файлов одновременно, это бизнес-решение). И поскольку я хочу прикрепить тот же прослушиватель событий к этой новой кнопке, вот что я сделал:
// CloneButton JS File
import 'registerFileUploadEvents' from './FileUpload.js'
// ... after adding cloned fileupload button
registerFileUploadEvents()
Так что это отлично работает во всех других браузерах, имя загруженного файла отображается в каждом новом компоненте, например:
———Компонент загрузки файлов 1——— xxx.jpg
———Компонент загрузки файлов 2——— xyz.png
Проблема в IE11, который делает что-то вроде этого:
———Компонент загрузки файлов 1——— xyz.png
———Компонент загрузки файлов 2——— (пусто)
Т. е. когда я нажимаю кнопку «Загрузить» во втором компоненте и загружаю файл xyz. png, вместо того, чтобы поместить имя файла xyz.png во второй компонент, он заменяет имя файла первого компонента.
It seemed to me that this is a case of the fileInput variable being cached, so I used closure to try and retain the scope:
export function registerFileUploadEvents() {
const fileUploadElements = document.querySelectorAll('.file-upload')
Array.prototype.forEach.call(fileUploadElements, (fileUploadElement) => {
const fileInput = fileUploadElement.querySelector('input[type="file"]')
fileInput.addEventListener('change', seriouslyMan(fileInput))
})
}
function seriouslyMan(fileInput) {
console.log(fileInput.getAttribute('id')) // For normal browsers and IE, logs respective IDs of 1st and second component
return function() {
console.log('fileinput should be scoped correctly', fileInput) // For normal browsers, when clicked 2nd component, 2nd component's DOM element is logged but for IE, the first component's DOM element is still logged
}
}
Таким образом, эта возвращаемая функция должна сохранять ввод файла с правильной областью, но я понятия не имею, почему этого не происходит в IE.
Я также попытался зациклить ввод[тип=»файл»] напрямую, чтобы добавить прослушиватели событий, но произошло то же самое.
Затем я попытался создать новую функцию для подключения прослушивателя событий изменений напрямую и только к недавно клонированной кнопке загрузки:
newFileUploadElement.querySelector('input[type="file"]').addEventListener('change', (e) => {
const selectedFile = e.target.files[0]
if (selectedFile) {
e.target.closest('.file-upload').querySelector('.file-upload__filename').innerHTML = selectedFile.name
}
})
Еще раз, это отлично работает во всех браузерах, кроме IE, который снова помещает второе имя файла в первый компонент.
Затем я попытался не добавлять прослушиватель событий во второй компонент, и снова при нажатии на 2-й компонент он запускает событие изменения. Заполнение первого компонента, конечно. Т. е. только, конечно.
К настоящему времени я полностью запутался и больше не знаю, как это отладить. Я упустил что-то очевидное? Любые предложения о том, как это отладить, будут высоко оценены.
Заранее спасибо за любую помощь.
Комментарии:
1. Насколько я знаю, IE не поддерживает функции со стрелками, вы можете это проверить. Могут возникнуть и другие проблемы. Если вы можете предоставить минимальный пример фрагмента кода, который может воспроизвести проблему, это поможет решить проблему.