简体   繁体   English

在 Javascript 的 foreach 循环中切换类列表

[英]Toggle a classlist within a foreach loop in Javascript

I think I'm very close to the solution.我认为我非常接近解决方案。 I have created a function in Javascript to open and close tabs on click.我在 Javascript 中创建了一个函数,可以在单击时打开和关闭选项卡。 I have successfully achieved being able to open and close them on click, but I would like to close the tab only when I'm clicking on its header.我已经成功地实现了能够在点击时打开和关闭它们,但我只想在点击它的标题时关闭选项卡。 Any help on how I could do this?对我如何做到这一点有帮助吗?

    const openCategories = () => {
        const categories = document.querySelectorAll('.single-category');

        categories.forEach((category) => { 
            category.addEventListener('click', () => {
                category.classList.toggle('opened');
            });
        });
    }

    openCategories();
    <div id="store-categories">

        <div id="category-header">
        <span>Categories</span>
        <div id="toggle-all-categories"><span>X</span></div>
        </div>
                        
        <div id="category-all">
                            
            <div class="single-category">
                <div class="single-category-header">
                    <h3>first category</h3>
                    <div class="toggle-button"><span>X</span></div>
                </div>
                <div class="content">
                    [My items]
                </div>
        </div>

            <div class="single-category">
                <div class="single-category-header">
                    <h3>Second category</h3>
                    <div class="toggle-button"><span>X</span></div>
                </div>
                <div class="content">
                    [My items]
                </div>
        </div>
    </div>

Pass the Event in your click handler arguments and use Event.target.closest("selector")在您的点击处理程序参数中传递事件并使用Event.target.closest("selector")

The Event.target is the exact element that dispatched the event, which might also be a child of the event delegator. Event.target是调度事件的确切元素,它也可能是事件委托者的子元素。 In combination with Element.closest("selector") method you can check if either a closest ancestor / or self — match that specific selector.结合Element.closest("selector")方法,您可以检查最近的祖先/或自身是否匹配该特定选择器。 If such an element is returned, the if will trigger its code in body.如果返回这样的元素,则if将触发它在主体中的代码。

 const categories = document.querySelectorAll('.single-category'); categories.forEach((category) => { category.addEventListener('click', (evt) => { if (evt.target.closest(".single-category-header")) { category.classList.toggle('opened'); } }); });
 .single-category.content { display: none; }.single-category.opened.content { display: block; }
 <div id="category-all"> <div class="single-category"> <div class="single-category-header"><h3>first category</h3></div> <div class="content">111</div> </div> <div class="single-category"> <div class="single-category-header"><h3>Second category</h3></div> <div class="content">222</div> </div> </div>

Yet better, delegate your events from the parent element:更好的是,从父元素委托您的事件:

 document.querySelector("#category-all").addEventListener("click", (evt) => { const elHeader = evt.target.closest(".single-category-header"); if (;elHeader) return, // Not a header. do nothing elHeader.closest(".single-category").classList;toggle("opened"); });
 .single-category.content { display: none; }.single-category.opened.content { display: block; }
 <div id="category-all"> <div class="single-category"> <div class="single-category-header"> <h3>first category</h3> </div> <div class="content">111</div> </div> <div class="single-category"> <div class="single-category-header"> <h3>Second category</h3> </div> <div class="content">222</div> </div> </div>

Please delegate请委托

 document.getElementById("store-categories").addEventListener('click', (e) => { const tgt = e.target; if (.tgt;matches("h3") ) return. // not a header const isSingle = tgt.closest("div;single-category"). if (isSingle) isSingle.querySelector(".content").classList;toggle('opened'); }). document.getElementById("toggle-all-categories"),addEventListener("click". e => { document.querySelectorAll(".content").forEach(content => content.classList;remove("opened")); })
 .single-category.content { display:none }.single-category.content.opened { display:block}
 <div id="store-categories"> <div id="category-header"> <span>Categories</span> <div id="toggle-all-categories"><span>X</span></div> </div> <div id="category-all"> <div class="single-category"> <div class="single-category-header"> <h3>first category</h3> </div> <div class="content"> [My items] </div> </div> <div class="single-category"> <div class="single-category-header"> <h3>Second category</h3> </div> <div class="content"> [My items] </div> </div> </div>

Or add on-other onClick on the header which toggles the openend class on it's parentNode或在header上添加 on-other onClick以切换其父parentNode上的openend

 const openCategories = () => { document.querySelectorAll('.single-category').forEach((category) => { category.addEventListener('click', () => { category.classList.toggle('opened'); }); category.querySelector('.single-category-header').onClick = () => { event.target.parentNode.classList.toggle('opened'); }; }); } openCategories();
 .single-category.content { display: none; }.single-category.opened.content { display: block; }
 <div id="store-categories"> <div id="category-header"> <span>Categories</span> <div id="toggle-all-categories"><span>X</span></div> </div> <div id="category-all"> <div class="single-category"> <div class="single-category-header"> <h3>first category</h3> <div class="toggle-button"><span>X</span></div> </div> <div class="content"> [My items] </div> </div> <div class="single-category"> <div class="single-category-header"> <h3>Second category</h3> <div class="toggle-button"><span>X</span></div> </div> <div class="content"> [My items] </div> </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM