导航栏类型错误:无法读取 null 的属性“classList”

时间:2021-01-12 13:22:53

标签: javascript html for-loop

我正在尝试为 html 实现一个导航栏,它具有动态切换页面的效果,而不是通过 href 更改链接。我用来完成此操作的技巧是将 classListis-active 添加到 div 标记中的 section 元素。

这是生成的 HTML 的示例代码: navBar.js

const navbarItem = [
    {
        navitem : "About",
        link: 1
    },
    {
        navitem : "Legal",
        link: 2
    },
    {
        navitem : "Contact",
        link: 3
    }
];

window.onload = function navLoad() {
    const navbar = document.getElementById('navbar');
    navbar.innerHTML = 
    `
        <div class="toggle">
            <i class="fa fa-bars menu" aria-hidden="true"></i>
        </div>
        <ul class="nav-list">
            <li class="tab is-active">
                <a onclick="renderNav()">Home</a>
            </li>
            ${navbarItem.map(loadNavitems).join(" ")}
        </ul>
    `
}

function loadNavitems(navItems) {
    return `
            <li class="tab">
                <a data-switcher data-id="${navItems.link}" onclick="renderNav(); navSwap();">${navItems.navitem}</a>
            </li>
        `
}

function renderNav(){
    const pages = document.getElementById('main');
    document.getElementById('alphabetButtons').style.display = "block";
    pages.innerHTML = 
    `
        <section class="pages">
             ${navbarItem.map(item => `
                <div class="page" data-page="${item.link}">
                    <h1>${item.navitem}</h1>
                </div>
             `).join('')}
        </section>
    `
};

这是负责页面切换的代码: navSwitcher.js

function navSwap() {
    const tab_switchers = document.querySelectorAll('[data-switcher]');

    for (let input of tab_switchers) {
        const page_id = input.dataset.switcher;
        console.log(page_id);
        input.addEventListener('click', function () {
            
            if(document.querySelector('.nav-list .tab.is-active')){
                document.querySelector('.nav-list .tab.is-active').classList.remove('is-active');
                console.log('removed'); 
            }
            if(input.parentNode.classList.contains('tab')){
                input.parentNode.classList.add('is-active');
            }
            //SwitchNav(page_id);
        });
    }
}

function SwitchNav(page_id) {
    const currentPage = document.querySelector('.pages .page');
    const next_page = document.querySelector(`.pages .page[data-page="${page_id}"]`);
    console.log(next_page);
    if(document.querySelector('.pages .page.is-active')){
        document.querySelector('.pages .page.is-active').classList.remove('is-active');
    }
    next_page.classList.add('is-active');
    
}

更新:问题是当尝试将 [data-page="${page_id}"] 放在 .page 之后的 querySelector 时导致错误出现。控制台记录时,[data-page="${page_id}"] 将返回 null。这很奇怪,因为 data-page 在保存类页面 div 的 renderNav 函数中被正确命名。

因此我现在的假设是问题来自 [data-page="${page_id}"] 函数中的 SwitchNav(page_id)我的问题是,如果一切都正确命名,为什么会发生这种情况?

已尝试修复:

  • 尝试将 for/of 循环更改为 navSwap 函数内的常规 for 循环。
  • 在 navSwap 函数中,const page_id = input.dataset.tab; 已更改为 const page_id = input.dataset.switcher;,现在返回 3 个项目。

1 个答案:

答案 0 :(得分:0)

所以经过一番挖掘,最后它实际上是 const page_id = tab_switcher.dataset.tab; 返回 undefined,因此导致错误发生。实际上它返回的是 id,所以我将其更改为 tab_switcher.dataset.id;

这是对代码的最后一次尝试(我将所有内容都放在一个文件中): navBar.js

const navbarItem = [
    {
        navitem : "About",
        link: 1
    },
    {
        navitem : "Legal",
        link: 2
    },
    {
        navitem : "Contact",
        link: 3
    }
];

window.onload = function navLoad() {
    
    const navbar = document.getElementById('navbar');
    navbar.innerHTML = 
    `
        <div class="toggle">
            <i class="fa fa-bars menu" aria-hidden="true"></i>
        </div>
        <ul class="nav-list">
            <li class="tab is-active">
                <a onclick="renderNav()">Home</a>
            </li>
            ${navbarItem.map(loadNavitems).join(" ")}
        </ul>
    `
}

function loadNavitems(navItems) {
    return `
            <li class="tab">
                <a data-switcher data-id="${navItems.link}" onclick="renderNav(); navSwap();">${navItems.navitem}</a>
            </li>
        `
}

function renderNav(){
    const pages = document.getElementById('main');
    document.getElementById('alphabetButtons').style.display = "block";
    pages.innerHTML = 
    `
        <section class="pages">
             ${navbarItem.map(item => `
                <div class="page" data-page="${item.link}">
                    <h1>${item.navitem}</h1>
                </div>
             `).join('')}
        </section>
    `
};

function navSwap() {
    const tab_switchers = document.querySelectorAll('[data-switcher]');

    for (let i = 0; i < tab_switchers.length; i++) {
        const tab_switcher = tab_switchers[i];
        const page_id = tab_switcher.dataset.id;
        tab_switcher.addEventListener('click', function(){
            document.querySelector('.nav-list .tab.is-active').classList.remove('is-active');
            tab_switcher.parentNode.classList.add('is-active');
            SwitchNav(page_id);
        });
    }
}

function SwitchNav(page_id) {
    const currentPage = document.querySelector('.pages .page');
    const next_page = document.querySelector(`.pages .page[data-page="${page_id}"]`);
    console.log(next_page);
    if(document.querySelector('.pages .page.is-active')){
       currentPage.classList.remove('is-active');
    }
    if(document.querySelector('.pages .page')){
       next_page.classList.add('is-active');
    }
}

虽然代码生成了预期的结果,但我必须在标签上单击两次才能触发它的 onclick 事件。如果有人知道为什么会发生这种情况,那么在评论中了解会很有帮助。

另外让我知道这是否是一个可行的解决方案。再次感谢:)