jQuery如何检测路径变化?LinkedIn扩展脚本适配求助
Got it, let's tackle this head-on. Your original code relies on the hashchange event, but LinkedIn doesn't use hash-based routing anymore—it uses the History API (pushState/replaceState) for AJAX-powered navigation. That's why your listener never fires when clicking header links. Here's how to fix it:
Step 1: Capture All Route Changes
The History API doesn't fire a native event when pushState or replaceState is called, so we need to "patch" these methods to trigger a custom event whenever the route updates. We'll also add support for browser back/forward navigation with the popstate event.
// Override History API methods to dispatch a custom statechange event (function(history) { const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function(state) { const result = originalPushState.apply(this, arguments); window.dispatchEvent(new Event('statechange')); return result; }; history.replaceState = function(state) { const result = originalReplaceState.apply(this, arguments); window.dispatchEvent(new Event('statechange')); return result; }; })(window.history); // Catch browser back/forward navigation too window.addEventListener('popstate', () => window.dispatchEvent(new Event('statechange')));
Step 2: Wait for DOM to Fully Update
LinkedIn loads content asynchronously, so even when the route changes, the DOM isn't immediately ready to scrape. We'll use MutationObserver to watch the main content container and trigger our scrape logic only when new content is fully loaded.
// Listen for our custom route change event window.addEventListener('statechange', () => { console.log("PATH CHANGED"); monitorLinkedInContent(); }); // Initialize on first page load $(function() { console.log("LOADED"); monitorLinkedInContent(); }); // Monitor the main content container for updates function monitorLinkedInContent() { // Target LinkedIn's main content container (adjust selector if needed) const mainContainer = document.querySelector('.scaffold-layout__main'); if (!mainContainer) return; // Configure observer to watch for new child elements const observerConfig = { childList: true, subtree: true }; const contentObserver = new MutationObserver((mutations) => { // Check if meaningful new content was added const hasNewContent = mutations.some(mutation => mutation.addedNodes.length > 0 && mutation.addedNodes[0].nodeType === Node.ELEMENT_NODE ); if (hasNewContent) { console.log("DOM updated—ready to scrape!"); scrapeUpdatedDOM(); // Stop observing after content loads to avoid duplicate triggers from minor DOM tweaks contentObserver.disconnect(); } }); // Start monitoring the main container contentObserver.observe(mainContainer, observerConfig); // If content is already loaded on initial page load, scrape immediately if (mainContainer.children.length > 0) { scrapeUpdatedDOM(); } } // Your custom DOM scraping logic goes here function scrapeUpdatedDOM() { // Example: Grab the current page's primary title const pageTitle = document.querySelector('.feed-identity-module__name')?.textContent.trim() || "Unknown Page"; console.log("Scraped content:", pageTitle); // Add your own scraping logic here (e.g., extract job details, profile info) }
Quick Tips
- Selector Adjustment: LinkedIn occasionally updates its DOM classes. If
.scaffold-layout__maindoesn't work, use your browser's dev tools to inspect the main content area—common alternatives are.core-railor.artdeco-page__content. - Avoid Over-Observing: We disconnect the
MutationObserverafter content loads to prevent unnecessary triggers from minor DOM changes (like hover states or button animations). - Test Edge Cases: This covers all navigation scenarios: clicking header links, searching, scrolling feeds, and using browser back/forward buttons.
内容的提问来源于stack exchange,提问作者bigpotato

