Как исправить Uncaught TypeError: невозможно прочитать свойства null (чтение «addEventListener») «loadeddata» в мобильном аудио API

Я следил за этим видео на YouTube https://www.youtube.com/watch?v=1-CvPn4AbT4, чтобы создать мобильный аудиоплеер с плейлистом для встраивания на музыкальный веб-сайт. В 1:12:16 я застрял с чтением ошибки; Uncaught TypeError: Не удается прочитать свойства null (чтение «addEventListener»). Я запустил его в валидаторе js и получил; Функции, объявленные внутри циклов, ссылающиеся на переменную внешней области видимости, могут привести к путанице в семантике. (liAudioTag). Я пытался изменить имя, но не идет. Как я могу это исправить?

Я ни в коем случае не являюсь экспертом в javascript или создании приложений, но я изо всех сил стараюсь учиться. Любая помощь будет оценена по достоинству.

const ulTag = wrapper.querySelector("ul");//1:07:10

for (let i = 0; i < allMusic.length; i++) {
    let liTag = `<li>
                    <div class="row">
                        <span>${allMusic[i].name}</span>
                        <p>${allMusic[i].artist}</p>
                    </div>
                    <audio class="${allMusic[i].src}" src="media/${allMusic[i].src}.mp3"></audio>
                    <span id="${allMusic[i].src}" class="audio-duration">3:40</span>
                </li>`;
    ulTag.insertAdjacentHTML("beforeend", liTag);//1:08:28
    
    let liAudioDuaration = ulTag.querySelector(`#${allMusic[i].src}`);//1:10:34
    let liAudioTag = ulTag.querySelector(`.${allMusic[i].src}`);//1:11:29
    
    liAudioTag.addEventListener("loadeddata", ()=>{
        let audioDuration = liAudioTag.duration;    
        let totalMin = Math.floor(audioDuration / 60);
        let totalSec = Math.floor(audioDuration % 60);
        if (totalSec < 10){//add 0 if sec less then 10
          totalSec = `0${totalSec}`;
        }
        liAudioDuaration.innerText = `${totalMin}:${totalSec}`;
    });
    
}

Также; да, я вижу, что liAudioDuaration написано неправильно, но это не имеет значения.

mim 20.11.2022 19:56

«Я запустил его в валидаторе js и получил: функции, объявленные в циклах, ссылающихся на переменную внешней области видимости, могут привести к запутанной семантике». - похоже, вы поместили код в линтер, который не поможет вам с этой ошибкой. Предупреждение о функциях в циклах не имеет значения - оно не имеет ничего общего с ошибкой, которую вы получаете, и нет проблем с определением прослушивателя событий в цикле в вашем коде, поскольку вы используете объявления let (const будет даже лучше).

Bergi 20.11.2022 21:25

«TypeError: Cannot read properties of null (reading ‘addEventListener’)» означает, что liAudioTag является null, потому что ulTag.querySelector(`.${allMusic[i].src}`) вернул null. Отладьте, какой селектор вы использовали. Покажите нам, что такое значение allMusic[i].src — скорее всего, это недопустимое значение атрибута класса, а также недопустимый селектор.

Bergi 20.11.2022 21:27

Спасибо за ответ. Я не был уверен, получу ли я его. Итак, ваш ответ полезен, но, как я уже сказал, я новичок, но пытаюсь учиться. Я не научился «Отлаживать», но, может быть, это то, о чем вы просите?

mim 20.11.2022 21:35

** let allMusic = [ { name: "1. Причины причин", artist: "Jeff Jirout", img: "4_ev_run", src: "Causes of the Causes" }, { name: "3. Forever On The Беги", исполнитель: "Джефф", изображение: "AJWslowroll", источник: "Forever On The Run" } ] **

mim 20.11.2022 21:35

О да. Forever On The Run не очень хорошее название класса - это несколько классов. И .Forever On The Run не выберет ваш элемент. Не используйте произвольные значения в HTML. Вместо этого используйте индекс i в качестве правильного идентификатора, например <audio id="audio${i}">… <span id="duration${i}">…, затем document.getElementById("audio"+i)

Bergi 20.11.2022 21:41

вау... БОЛЬШОЕ СПАСИБО. Я смотрел на это в течение нескольких дней. Я удалил пробелы в разделе allMusuc, и теперь он работает как шарм. Ваш спасатель жизни. Хорошего курортного сезона. ваше здоровье

mim 20.11.2022 21:47

Берги, могу я дать тебе значок или что-то в этом роде за помощь?

mim 20.11.2022 21:52

Я изменил #duration${i} и #audio${i}, а также идентификатор звука вместо класса, и все работает отлично. Еще раз спасибо Берги.

mim 20.11.2022 22:32
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
учебник по Javascript
учебник по Javascript
JavaScript - это язык программирования, который обычно используется для добавления интерактивности и других динамических функций на веб-сайты. Он...
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
D3.js - это обширная библиотека, используемая для привязки произвольных данных к объектной модели документа (DOM). Мы разберем основные варианты...
Освоение принципов SOLID в JavaScript: Пошаговое руководство
Освоение принципов SOLID в JavaScript: Пошаговое руководство
Принцип единой ответственности (SRP): класс должен иметь только одну причину для изменения. Другими словами, у него должна быть только одна...
JavaScript - For Loop
JavaScript - For Loop
Наиболее используемая компактная форма оператора цикла.
Неделя 1 - Карточки с временной шкалой
Неделя 1 - Карточки с временной шкалой
Поскольку это была первая неделя, я решил начать с простого. Предполагалось, что у меня будет временная шкала с несколькими карточками, которые можно...
0
9
480
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

const ulTag = wrapper.querySelector("ul");//1:07:10

for (let i = 0; i < allMusic.length; i++) {
    const liTag = `<li>
                <div class="row">
                    <span>${allMusic[i].name}</span>
                    <p>${allMusic[i].artist}</p>
                </div>
                <audio id="audio${i}" src="media/${allMusic[i].src}.mp3"></audio>
                <span id="duration${i}" class="audio-duration">3:40</span>
            </li>`;
    ulTag.insertAdjacentHTML("beforeend", liTag)
    
    const liAudioDuaration = ulTag.querySelector(`#duration${i}`);
    const liAudioTag = ulTag.querySelector(`#audio${i}`);
    
    liAudioTag.addEventListener("loadeddata", () => {
        const audioDuration = liAudioTag.duration;    
        const totalMin = Math.floor(audioDuration / 60);
        let totalSec = Math.floor(audioDuration % 60);
        if (totalSec < 10){//add 0 if sec less then 10
          totalSec = `0${totalSec}`;
        }
        liAudioDuaration.innerText = `${totalMin}:${totalSec}`;
    });
}

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