如何用jQuery实现多按钮滚动至浏览器顶部时执行操作(单按钮正常多按钮报错)
Hey there! Let's figure out why your script breaks when adding multiple buttons and get it working smoothly again.
Why You're Seeing That Error
The Uncaught TypeError: Cannot read property 'top' of undefined happens because your original script was built to work with a single button—when you add more, it's probably trying to access a button element that doesn't exist (like using getElementById which only grabs the first matching element) or you're not looping through all buttons correctly, leading to an undefined reference when trying to read the top property from getBoundingClientRect().
Step-by-Step Fix
Here's how to adjust your script to handle multiple buttons reliably:
1. Add a Shared Class to All Buttons
First, give all your trigger buttons the same CSS class so we can select them easily:
<button class="scroll-trigger-btn">First Button</button> <button class="scroll-trigger-btn">Second Button</button> <button class="scroll-trigger-btn">Third Button</button>
2. Rewrite the Script to Handle Multiple Elements
Instead of targeting a single button, we'll grab all buttons with our shared class, then check each one's position on scroll:
// Grab all our trigger buttons const triggerButtons = document.querySelectorAll('.scroll-trigger-btn'); // Define the action you want to run when a button hits the top function triggerButtonAction(button) { // Replace this with your actual desired action button.classList.add('triggered'); console.log(`Button "${button.textContent}" reached the top!`); } // Check each button's position on scroll function checkScrollPositions() { triggerButtons.forEach(button => { const buttonRect = button.getBoundingClientRect(); // Check if the button's top edge has reached or passed the viewport top if (buttonRect.top <= 0) { // Add a data attribute to prevent repeating the action nonstop if (!button.dataset.hasTriggered) { triggerButtonAction(button); button.dataset.hasTriggered = 'true'; } } else { // Optional: Reset the button if it scrolls back into view button.dataset.hasTriggered = 'false'; button.classList.remove('triggered'); } }); } // Attach the scroll listener window.addEventListener('scroll', checkScrollPositions); // Check positions once on page load in case buttons are already at the top window.addEventListener('load', checkScrollPositions);
Key Improvements
querySelectorAll: This grabs every button with our class, so we don't miss any.- Per-Button Checks: Using
forEachlets us run the position check on each button individually, so we never try to accesstopon an undefined element. - Prevent Duplicate Triggers: The
data-has-triggeredattribute stops the action from running hundreds of times as the user scrolls past the button.
What Was Wrong With Your Original Script?
Chances are your original code looked something like this:
// Only grabs the first button with this ID const button = document.getElementById('my-button'); window.addEventListener('scroll', () => { const rect = button.getBoundingClientRect(); if (rect.top <= 0) { // Do something } });
When you added more buttons, you either reused the same ID (which is invalid HTML) or didn't adjust the script to select and loop through all new buttons—leading to button being undefined for elements that weren't the first one, hence the error.
内容的提问来源于stack exchange,提问作者Mariton

