laravelvue.jsvue-componentvue-routerlaravel-vue

Laravel-vuejs (Vue Router) Javascript not working in onchange url


In my project, when I move from page to page with <router-link>, JavaScript does not work, look at the image to understand what I mean.

enter image description here

The first time when I refresh the page, everything works, but when I go, for example, to the test page (from localhost:8000/ to localhost:8000/test), JavaScript doesn't work, anyone help me?

app.blade.php:

<!DOCTYPE html>
<html>
    <head>
        <title>Vue App</title>
        <link rel="stylesheet" type="text/css" href="{{mix('css/app.css')}}">
    </head>
    <body>

        <div id="app">
            <app></app>
        </div>

        <script src="{{mix('js/app.js')}}"></script>
        <script src="{{mix('js/main.js')}}" async></script>

    </body>
</html>

my App.vue

<template>
    <div class="root">
        <Header/>
        <router-view></router-view>
    </div>
</template>
<script>
    import Header from '@layout/Header';
    export default 
    {
        components: 
        {
            Header
        },

    }
</script>

my Header.vue

<template>
    <header>
        <router-link :to="{name: 'home'}"> Home </router-link>
        <router-link :to="{name: 'test'}"> Teet </router-link>
    </header>
</template>

app.js:

require('./bootstrap');

import Vue from 'vue';
import VueRouter from 'vue-router';
import App from '@layout/App';
import {routes} from '@/routes';


Vue.use(VueRouter);

const router = new VueRouter({
    mode: 'history',
    routes
});


const app = new Vue({
    el: '#app',
    router,
    // components: { App }
    render : h => h(App)
});

routes.js:

import Home from '@views/Home';
import Test from '@views/Test';

export const routes = 
[
    {
        path: '/',
        name: 'home',
        component: Home
    },
    
    {
        path: '/test',
        name: 'test',
        component: Test
    },

]

my webpack.mix.js

const mix = require('laravel-mix');


mix.webpackConfig({
    resolve: {
        extensions: [ '.js', '.vue' ],
        alias: {
            '@': path.resolve(__dirname, 'resources/js/'),
            '@layout': path.resolve(__dirname, 'resources/js/layout'),
            '@views': path.resolve(__dirname, 'resources/js/views'),
            '@assets': path.resolve(__dirname, 'resources/assets/')
        }
    }
});

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

mix.copy('resources/assets/js/main.js', 'public/js/main.js');

I will be very happy if you help me. Thanks.


Solution

  • Ah well, I understand what you want. You want to call up the JavaScript file in all components. For example, the init.js for JavaScript plugins such as select2, datapicker, etc ... must be called in all components, did I get you right?

    Anyway

    #1 Create a file external.js in path resources/js/

    external.js

    function add_script(src) {
        if(document.querySelector("script[src='" + src + "']")){ return; }
        let script = document.createElement('script');
        script.setAttribute('src', src);
        script.setAttribute('type', 'text/javascript');
        document.body.appendChild(script)
    }
    
    function rem_script(src) {
        let el = document.querySelector("script[src='" + src + "']");
        if(el){ el.remove(); }
    }
    

    In your app.js add

    import {add_script, rem_script} from './external';
    
    router.beforeEach((to, from, next) => {
    
    
      /* It would be nice to add a pre-loader here d
         so that the page design is not affecte
      */
      // Track your console :)
      console.log('Hi before load');
       
      // Add your script
      add_script('path/to/your_js');
      next()
    })
    router.afterEach(() => {
      // Here you can remove loader after loaded
    
    
      // Track your console :)
      console.log('Hi After load');
    
    
      // remove_included_js file but still working :)
      rem_script('path/to/your_js');    
    
    })
    

    Now this file path/to/your_js should be called in each component.

    Finish, that's it :)

    But I never advise you this way on large projects :) But as @equi and @Stefano A. Said, they are right.