Vue.js 2执行router.push时外部JS无法加载的问题排查
Hey there! I’ve run into this exact issue before with single-page apps—let’s break down why it’s happening and how to fix it quickly.
Why This Happens
When your app loads initially, your external JS files (like jQuery and datepicker) run once and bind to the DOM elements that exist at that time. But when you use $this.router.push('/dashboard'), your app doesn’t do a full page refresh—it just swaps out DOM content dynamically. Those new elements on the dashboard page never get initialized by your external scripts, which is why they’re not working.
Solutions to Try
1. Re-Initialize Scripts in the Target Component
The simplest fix is to re-run your JS initialization code after the new page’s DOM has fully loaded. If you’re using Vue (since you’re using $this.router), do this in the mounted() hook of your Dashboard component:
mounted() { // Wait for DOM to render, then initialize datepicker $(() => { $('.datepicker').datepicker(); }); }
For React, use the useEffect hook with an empty dependency array to run code once the component mounts:
import { useEffect } from 'react'; import $ from 'jquery'; function Dashboard() { useEffect(() => { $('.datepicker').datepicker(); }, []); return ( // Your dashboard JSX content ); }
2. Use Event Delegation for Dynamic Elements
If jQuery event handlers aren’t firing on dynamic elements, switch to event delegation. Bind to a parent element (like document) that exists from the start, instead of directly to the dynamic element:
// Instead of this (only works for initially loaded elements): $('.my-action-button').click(function() { // Your code here }); // Do this (works for dynamically added elements): $(document).on('click', '.my-action-button', function() { // Your code here });
3. Integrate Third-Party Scripts Into Your Build Flow (Recommended)
Instead of loading external JS via <script> tags in index.html, install them as npm packages and import them directly into components. This gives you better control over initialization and avoids global scope issues:
- Install the packages first:
npm install jquery jquery-ui-datepicker
- Import and initialize in your component:
import $ from 'jquery'; import 'jquery-ui-datepicker'; // Don't forget to import the CSS for datepicker! import 'jquery-ui-datepicker/dist/jquery-ui.css'; export default { mounted() { $('.datepicker').datepicker(); } }
4. Dynamically Load Scripts on Route Change (Emergency Fix)
If you can’t switch to npm packages, load scripts dynamically when navigating to the dashboard—just be careful to avoid duplicate loads:
// In your router configuration router.beforeEach((to, from, next) => { if (to.path === '/dashboard') { // Check if jQuery is already loaded if (!window.jQuery) { const jqueryScript = document.createElement('script'); jqueryScript.src = '/static/jquery.min.js'; jqueryScript.onload = () => { // Load datepicker after jQuery is ready const datepickerScript = document.createElement('script'); datepickerScript.src = '/static/datepicker.js'; datepickerScript.onload = () => { $('.datepicker').datepicker(); next(); }; document.body.appendChild(datepickerScript); }; document.body.appendChild(jqueryScript); } else { // Re-initialize datepicker since jQuery is already present $('.datepicker').datepicker(); next(); } } else { next(); } });
Final Notes
The best long-term fixes are option 1 and option 3—they fit cleanly with how SPAs work and avoid messy global script management. Event delegation is perfect for fixing event handler issues, while integrating packages gives you more control over dependencies.
内容的提问来源于stack exchange,提问作者Adarsh

