How to properly add multiple Vue components in app.js in Laravel - laravel

So, hi. I've been struggling for 4 hours to add at least two different Vue components to my app.js file which is located in js folder along with these vue components in my Laravel project.
I couldn't find any real solution on the internet since it didn't fix my problem.
I have tried something like
Vue.component('signature-element', require('./components/Signature.vue').default);
under the other component which works perfectly, but the problem is I can't make the app work with 2 or more components.
I've tried installing vue-router via npm and configuring a router but it didn't work too, somehow whole JS stopped without any errors in the command log in browser or in Mix.
I've also tried calling the import function instead of the first one I've mentioned, for example:
const componentVar = import ...;
inside vue:
new Vue({
components: { first, componentVar },
mounted() {}
});
But this also did not work unfortunately.

In the second example you're trying to registrate locally your components.
If you want to do this you can do it like this:
import first from './components/first'
import componentVar from './components/componentVar'
new Vue({
el: '#app',
components: {
'first': first,
'componentVar': componentVar
}
})
Instead if you want to use the first example this means you want to register your components globally. That means they can be used in the template of any root Vue instance (new Vue) created after registration
Example:
Vue.component('signature-element', { /* ... */ })
new Vue({ el: '#app' })
Then in your view
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>

Related

VueJS Performance Questions

I'm working on a browser extension that uses Vue Cli with Vue Bootstrap. I've already optimized my Vue Bootstrap imports to only load the components and icons I use in the project. I also have lazy loaded route components, but I still see a long time to get to the created hook of my first component. Here's a code extract:
Main entry point
console.info("Loaded in " + (new Date().getTime() - global.start) + "ms")
require("#/App.js")
App.js
import Vue from "vue"
import * as Sentry from "#sentry/vue"
import { Integrations } from "#sentry/tracing"
import App from "#/App.vue"
import router from "#/common/router"
import store from "#/common/store"
import { get } from "#/common/api"
...
import {
ModalPlugin,
ButtonPlugin,
TabsPlugin,
DropdownPlugin,
AlertPlugin,
ToastPlugin,
FormInputPlugin,
FormRadioPlugin,
...
BIconArrowRightShort,
BIconArrowDownSquareFill,
} from "bootstrap-vue"
Vue.use(ModalPlugin)
Vue.use(ButtonPlugin)
Vue.use(TabsPlugin)
...
Vue.component("BIcon", BIcon)
Vue.component("BIconX", BIconX)
Vue.component("BIconArrowLeft", BIconArrowLeft)
Vue.component("BIconMailbox", BIconMailbox)
Vue.component("BIconFolderPlus", BIconFolderPlus)
Vue.component("BIconEnvelope", BIconEnvelope)
...
global.vm = new Vue({
router,
store,
render: h => h(App),
created() {
this.$router.push({ name: "Responses" })
...
})
}
And here's my component file that gets loaded first:
<template>
<div>
<div>
...
</div>
</div>
</template>
<script>
let now = new Date().getTime()
console.info("SFC file loaded in " + (now - global.start) + "ms")
import ... from "#/common/components/..."
export default {
...
mounted() {
let now = new Date().getTime()
...
</script>
<style lang="scss">
...
</style>
When I benchmark times, this is what I get:
SFC file loaded at 46ms (at the top of the script section)
Created Hook starts a 177ms
Mounted Hook starts at 308ms
I'm wondering what takes so long in the created hook (I don't do much, just checking the $route parameters). 150ms to just go through the created hook seems like a lot?
Here's the created hook:
console.info("Created Hook in " + (new Date().getTime() - global.start) + "ms")
if (this.$route.params.xx {
this.... = this.$store.state.xxxx.find(e => {
return e.uuid == .......
})
}
Performance loading the extension is important for the user experience, and it always feels a little sluggish when opening the extension popup.
Any idea on what could delay the loading like that?
Thanks!
The first thing that I notice is that you are doing a route.push on App created hook, that means that the router already solve the first route (probably '/') and after that you are adding another route (but not immediately) and then the router is solving that new route.
For a faster boot why don't you add a redirect to the route:
//...routes
{
path: '/',
redirect: {name: 'Responses'}
}
If you have the opportunity to change to Vue3 then maybe you could also perceive a performance boost since Vue2 has an always present GlobalAPI and Vue3 is doing a tree shaking and ignoring the unused stuff after building.
Note: Make sure you are testing it with a production environment, because if you are using the vue-cli to serve the content then the startup will include a lot of overhead
Thanks guys! Actually the default route is already redirecting to Responses, and removing the push doesn't change much.
Unfortunately I can't really migrate to Vue 3 as I rely on dependencies that do not fully support Vue 3 (Vue BS being an important one).
I'm guessing that's as much as I can do at this point. Just wondering if there's any way with Vue Cli to open the window browser extension popup immediately and load Vue afterwards (right now, it's waiting for the whole thing to be loaded and then opens the popup which gives a 300ms delay between the click and the window actually opening).
There is much more what happens between created and mounted hooks - it's not just the code in all created hooks what is running. Check the Vue component lifecycle
As you are using Vue SFC'c and probably Webpack, template compilation is out of the question but still, after created Vue is executing render functions of all components (producing VDOM) and creating real DOM elements based on VDOM (rendering whole app). So depending on number of components and elements, 150ms is not that bad...

Problems with vue in laravel

I am trying to implement
Media manager 3.6.7 to my laravel 5.8 project but i am facing problems with VUE. (This is my first time using it).
In console it gave me two errors: Error in console with BLANK page but when i click on page source i can see that the page is rendered: Page source
I think I am stuck at this:
// app.js
window.Vue = require('vue')
require('../assets/vendor/MediaManager/js/manager')
new Vue({
el: '#app'
})
Where should i put it ? If I put it in media.blade.php i got Require is not a function. If i include require, there is another error
Module name "vue" has not been loaded yet for context: _. Use require([])
If i use require(['vue']) i got like, 20 errors..
What is the problem here? Previous steps are completed succesffully.
The error clearly says that you have not registered the component properly.
In app.js file:
import ComponentA from '/*path of the file*/'
import ComponentB from '/*path of the file*/'
new Vue({
el: '#app',
components: {
'my-notification': ComponentA,
'media-manager': ComponentB
}
})

Swiper navigation not working - Webpack (Laravel)

Swiper is initializing without problems, for some reason, pagination (and everything else...) is not working.
I'm using webpack on laravel (5.8), the version of swiper i'm using is 6.4.5. No errors in console
This is my code:
// import Swiper JS
import Swiper, { Pagination } from 'swiper';
// import Swiper styles
import 'swiper/swiper-bundle.css';
// configure Swiper to use modules
Swiper.use([Pagination]);
var swiper = new Swiper('.swiper-container', {
direction: 'vertical',
loop: true,
autoplay: true,
grabCursor: true,
// If we need pagination
pagination: {
el: '.swiper-pagination',
clickable: true,
},
});
Outcome:
Swiper is created, pagination not working, autoplay not working, nothing is working only the swiper is created
I managed to resolve this issue, I'll post my answer if anyones has the same problem.
The version of swiper i'm currently using contains the vue integration, I'm not using the vue integration because i'm working with the version 2 of vue.js, swiper needs the version 3 of vue.js. So I commended out my vue instance, and everything started working, the issue was a conflict between vue.js and Swiper.
In the documentation you import the same way for vue and ES modules so i'm guessing there is some type of conflict.
So I moved my swiper import after the vue.js declaration:
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
require('./scripts/swiper');
And now everything is working

Multiple instances of VUEjs in laravel

Good morning! How can I work with multiple instances of VUEjs in Laravel?
I want to work with the components in some parts of the project and in other occasions I want to instantiate VUE directly in the view and do the logic there but I have the problem that I can't work with both at the same time.
If I want to work with the components I must leave the "const app new Vue" of the app.js file. But if I leave this file like this it won't work in the views.
how can i do it? Thank you!
app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
import VueSweetalert2 from 'vue-sweetalert2';
require('./bootstrap');
window.Vue = require('vue');
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.use(VueSweetalert2);
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('eliminar-registro', require('./components/EliminarRegistro.vue').default);
Vue.component('modal-encuestas', require('./components/ModalEncuestas.vue').default);
Vue.component('abrir-modal', require('./components/AbrirModal.vue').default);
Vue.component('ejemplo-prueba', require('./components/EjemploPrueba.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
Notice how your vue instance mounts to an element
const app = new Vue({
el: '#app',
});
This can be found in your app.blade.php or whatever layout you use
there will be a <div id="app"></div>
This is how you mount instances.
So now If you want a second instance
You can mount a second one to another div as long as the two divs are seperate
in app.js
const app = new Vue({
el: '#app',
});
const app = new Vue({
el: '#second-app',
});
Then in your app.blade.php
<div id="app"></div>
<div id="second-app"></div>
This will give you two seperate vue instances on the same page.

Registering Third-Party Vue Components in Laravel

I'm new to using Vue.js with Laravel and there is one thing I couldn't figure out.
When I write my own components, I know how to implement and register them into my project by using the app.js file.
My question is, how can I register third party components into Laravel? I'm trying to register Vue Form Wizard into my project, but I can't get it to work.
I've tried multiple ways to register the component:
// app.js file
require('./bootstrap');
window.Vue = require('vue');
Vue.component('form-wizard', require('./components/FormWizard.vue'));
const app = new Vue({
el: '#app'
});
My component file:
<script>
import VueFormWizard from 'vue-form-wizard';
import 'vue-form-wizard/dist/vue-form-wizard.min.css';
Vue.use(VueFormWizard)
</script>
My view called like so:
<form-wizard
#on-complete="onComplete"
color="#FFA500"
error-color="#a94442"
shape="tab"
next-button-text="Continue"
back-button-text="Previous"
finish-button-text="Complete"
></form-wizard>
What do I need to do to make this work?
You don't need to define a FormWizard component. Simply move the code in the script section of your component file to the app.js file:
// app.js file
require('./bootstrap');
window.Vue = require('vue');
import VueFormWizard from 'vue-form-wizard';
import 'vue-form-wizard/dist/vue-form-wizard.min.css';
Vue.use(VueFormWizard)
const app = new Vue({
el: '#app'
});
This will register the VueFormWizard component globally, meaning you can use the form-wizard tag in any template.

Resources