menu

Questions & Answers

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.

Answers(3) :

I don't see it breaks. If you think about missing alert message: you probably put it in App.vue component as part of created() or mounted() lifecycle hook. It's only showing once, because App.vue component stays loaded, and you are switching between Test.vue and Home.vue using router. App.vue doesn't go through its lifecycle hooks until refresh.

If you, however, want to execute part of the code on each route change, you should use navigation guards on vue router.

Comments:
2023-01-11 09:29:40
I want include my project js files for my theme, and main.js should contain my javascript code, for that's reasons should included in all pages. like you integrate a theme with laravel-vuejs. any help?
2023-01-11 09:29:40
this is my theme structure i.ibb.co/Pg1wRV3/Capture.png and i want include main.js in laravel-vuejs project
2023-01-11 09:29:40
You could import it in app.js file like: import '../project/js/main.js. You need to get the correct path

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.

router-link allows JS navigation in a router-enabled Vue.js application. This allows optimizing the user experience by reducing the amount of time required to load a new page. Specifically, the new page is injected into the DOM asynchronously.

To achieve your desired outcome, we could put the functionality we'd like to run on the page load in the mounted() method of the component:

//component Test
<template>
    <div>
      <span> Test Page </span>
    </div>
</template>
<script>
export default 
{
   data() {
      return { }
   },
   mounted() {
      alert('Page loaded!'); // JS functionality to be run on component mount
   }
}
</script>

If desired, we could load an external .js file in the mounted() method:

mounted() {
    let newScript = document.createElement('script')
    newScript.setAttribute('src', 'https://<URL>/script.js')
    document.head.appendChild(newScript)
}
Comments:
2023-01-11 09:29:40
Yes but i want load/include this main.js in all vue pages (component) should i write the same code in every page? that's is for me not logical, why i not include in app.js or index.blade.php. But i don't know why not working or what is the solutions, is exactly like when you include js library in your project, but as i said i'am new in vuejs and don't know how i solve this problem. Please help me.
2023-01-11 09:29:40
this is my theme structure i.ibb.co/Pg1wRV3/Capture.png and i want include main.js in laravel-vuejs project