网站JS加载正常但功能失效问题排查求助
Let’s break down why your Material Design drawer and "Servizi" dropdown are acting inconsistently, and walk through fixes to resolve it:
Core Root Cause: Race Conditions Between Async Loading & Component Initialization
The biggest culprit here is jQuery’s load() method runs asynchronously. Your Material Design (MD) JavaScript is likely trying to initialize the drawer and dropdown components before the external HTML files (header1.html, header2.html, header3.html) finish loading into the DOM. Some refreshes get lucky (MD init runs after HTML loads), others don’t—hence the intermittent missing elements and broken functionality.
Adjusting your JS load order doesn’t fix this because load() doesn’t block execution, so the race condition persists.
Fixes to Implement
1. Initialize MD Components Only After All HTML Loads Complete
Tie your MD component initialization directly to the completion of all load() calls using jQuery’s deferred promises. This ensures the DOM elements exist before MD tries to attach functionality:
function createHeaderandFooter() { $(function() { // Wrap each load operation in a promise const headerLoad = $(".mdl-layout__header").load("lib/header1.html").promise(); const drawerLoad = $(".mdl-layout__drawer").load("lib/header2.html").promise(); const dropdownLoad = $(".mdl-layout-custom__dropdown").load("lib/header3.html").promise(); const footerLoad = $("#footer").load("lib/footer.html").promise(); // Wait for all loads to finish before initializing components $.when(headerLoad, drawerLoad, dropdownLoad, footerLoad).done(function() { // Initialize Material Design components here // For Material Design Lite (MDL), use this to upgrade dynamic DOM elements: if (window.componentHandler) { componentHandler.upgradeDom(); // Optional: Target specific components for precision // componentHandler.upgradeElement(document.querySelector('.mdl-layout__drawer')); // componentHandler.upgradeElement(document.querySelector('.mdl-layout-custom__dropdown')); } }); }); }
2. Prevent Duplicate Initialization
If createHeaderandFooter() gets called multiple times (e.g., on page refreshes or route changes), duplicate initialization can cause conflicts. Add a guard clause to avoid this:
let headerFooterInitialized = false; function createHeaderandFooter() { if (headerFooterInitialized) return; $(function() { // ... existing load and promise logic ... $.when(...).done(function() { headerFooterInitialized = true; // Initialize MD components }); }); }
3. Confirm MD Component Dependencies Are Loaded
Double-check that you’re including the necessary MD modules for drawers and dropdowns. For example, if using Material Design Lite, ensure layout.js (for drawers) and menu.js (for dropdowns) are part of your loaded JS files—missing these will break functionality even if elements exist.
Debugging Steps to Validate
- Open your browser’s DevTools (F12) and go to the Console tab. Refresh the page multiple times—look for errors like "Cannot read property 'addEventListener' of null", which confirms MD is trying to init on a non-existent element.
- Add
console.log($(".mdl-layout__drawer").length)inside thedone()callback to verify the element exists before component initialization.
内容的提问来源于stack exchange,提问作者Luca Crippa

