Proper way to include JS files with Vue Router navigation

I’m having trouble with loading JavaScript files properly in my Vue application when using Vue Router. The issue is that my JS functions only work after I manually refresh the page with F5. When I navigate between routes using router-link, the JavaScript doesn’t load correctly for each component.

My setup:

I have a main app.html file:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My Vue App</title>
    <!-- CSS Libraries -->
    <link rel="stylesheet" href="./assets/libs/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="./assets/libs/datatables/datatables.min.css">
    <link rel="stylesheet" href="./assets/custom/main.css">
  </head>
  <body>
    <div id="root"></div>
    
    <!-- JavaScript Libraries -->
    <script src="./assets/libs/jquery/jquery.min.js"></script>
    <script src="./assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
    <script src="./assets/libs/datatables/datatables.min.js"></script>
    <script src="./assets/custom/app.js"></script>
  </body>
</html>

Project structure:

project/
├── app.html
├── /src
│   ├── /views
│   │   ├── /pages
│   │   │   └── UserProfile.vue
│   │   └── /shared
│   │       ├── Sidebar.vue
│   │       └── TopBar.vue
│   ├── /routing
│   │   └── routes.js
│   ├── Main.vue
│   └── index.js
└── /assets
    ├── /libs
    └── /custom

Router configuration:

import UserProfile from '@/views/pages/UserProfile.vue'

Vue.use(VueRouter)

const appRouter = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/dashboard',
      name: 'MainLayout', 
      component: MainLayout,
      children: [
        {
          path: 'profile',
          name: 'UserProfile',
          component: UserProfile
        }
      ]
    }
  ]
})

Should I move my JavaScript files to the /src/assets directory instead? What’s the correct approach to ensure scripts load properly when navigating between routes?

Moving your JS files to /src/assets won’t fix this. The real problem is DataTables needs to initialize after DOM elements load, but that doesn’t happen automatically when Vue Router navigates between pages. I hit this same issue with DataTables in Vue last year. What fixed it: import these libraries as modules in the components that actually need them, then call their init functions in the mounted hook. For DataTables, you’ll also need to destroy the table instance in beforeDestroy - otherwise you get memory leaks when users navigate away. Keep jQuery and Bootstrap in your main HTML since they’re global, but handle DataTables init per component.

exactly! each time a component loads, you shud run ur js in the mounted() lifecycle. vue router loads components instead of reloading the page, so your scripts gotta be local to the component to function right.

The issue arises because Vue Router caters to client-side navigation, causing your JavaScript in the primary HTML to execute only during the initial page load. For dynamic functionalities like DataTables, it’s crucial to place your scripts within the mounted() hook of each component. This ensures they run every time the respective component loads. While global libraries such as jQuery can remain in your HTML, ensure that any component-specific code resides within Vue’s lifecycle methods for effective execution during route changes. Additionally, consider moving away from jQuery to leverage Vue’s capabilities more effectively.