Home  >  Q&A  >  body text

scrollIntoView executes too early after forEach loop

I have the following two functions...

function sizeSearch(size) {
    const container = document.querySelector('ul.size-ranks');
    const rankElems = container.querySelectorAll('li');
    rankElems.forEach(e => {
        e.style.display = 'none';
        e.classList.remove('active');
    });

    const sizeID = size.replace(/\D/g,'') + '-rank';
    const sizeElem = document.getElementById(sizeID);
    if (sizeElem) {
        sizeElem.classList.add('active');
        sizeElem.style.display = '';
    } else {
        container.insertAdjacentHTML('beforeend', '<li class="empty-search">尺寸未找到</li>');
    }
}

function clearSizeSearch() {
    document.querySelectorAll('li.empty-search').forEach(e => e.remove());
    document.querySelectorAll('ul.size-ranks li').forEach(e => e.style.display = '');
    document.querySelector('ul.size-ranks li.active').scrollIntoView();
}

sizeSearch() function works normally. When the clearSizeSearch() function is called, all <li> elements redisplay as expected, and you can briefly see the expected .active The element scrolls into view, but then it immediately scrolls back on top of the container element (or maybe it re-renders this way after the DOM has finished settling?).

If I manually run document.querySelector('ul.size-ranks li.active').scrollIntoView(); in the console and then run clearSizeSearch(), then It just works. This, coupled with the fact that I can briefly see it scroll into view when clearSizeSearch() is run, seems to indicate that it may run before the previous command execution completes, but as far as I can tell, forEach()The default is not asynchronous, any command after it should not run before it completes.

P粉504920992P粉504920992421 days ago644

reply all(1)I'll reply

  • P粉633733146

    P粉6337331462023-09-17 17:56:18

    This is my solution.

    function clearSizeSearch() {
        document.querySelectorAll('li.empty-search').forEach(e => e.remove());
        document.querySelectorAll('ul.size-ranks li').forEach(e => e.style.display = '');
        setTimeout(() => {
            document.querySelector('ul.size-ranks li.active').scrollIntoView();
        }, 0);
    }

    reply
    0
  • Cancelreply