Vue 3 - how to include components and mixins with the root component? - vue.js

I try to convert the syntax from Vue 2 to Vue 3, but I'm not sure how to include the mixins and components, if you see this code from Vue 2:
import App from "./App.vue";
const app = new Vue({
mixins: [globalMixin],
router,
el: '#app',
store,
components: {
Thing,
Hello
},
render: h => h(App)
});
Here is the Vue 3 syntax, if I've understood it right:
const app = createApp(App)
app
.use(store)
.use(router)
app.mount('#app')
The vue 2 example has a mixin and two components, but how do I add that to the Vue 3 syntax?
You can add a component by doing : app.component('Thing', Thing) but that's only one component...should I add them one by one in that way? What about the mixins?

In Vue 3, it's possible to do local component registration and mixins in the root component (useful when trying to avoid polluting the global namespace). Use the extends option to extend the component definition of App.vue, and then add your own mixins and components options:
import { createApp } from 'vue'
import App from './App.vue'
import Hello from './components/Hello.vue'
import Thing from './components/Thing.vue'
import globalMixin from './globalMixin'
createApp({
extends: App,
mixins: [globalMixin],
components: {
Hello,
Thing,
}
}).mount('#app')
Registering the component one at a time seems like the way to go, especially if there are only a few components.
demo

In Vue 3, you can use the application API mixin method.
import { createApp } from 'vue'
import App from './App.vue'
import globalMixin from './globalMixin'
const app = createApp(App)
app.mixin(globalMixin)
app.mount('#app')
For components, you can add them one by one. I prefer it this way because it is cleaner.

Related

vue 3 before create event in main.js

I'm trying to use beforeCreate in main.js. What is the equivalence of this code in Vue 3?
new Vue({
el: '#app',
router,
components: { App },
store: store,
beforeCreate() { this.$store.commit('initialiseStore');},
template: '<App/>'
})
beforeCreate() still exists in Vue 3's Options API.
For that code snippet, the only differences in Vue 3 would be:
The creation of the app instance is now done via Vue.createApp().
Note: In the following example, we're using extends: App here so that we could add the beforeCreate() hook. Otherwise, we could simply do createApp(App) instead.
The Vue plugins are installed off of the app instance's use() method.
The mounting is done via the app instance's mount() method.
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
1️⃣
createApp({
extends: App,
beforeCreate() { this.$store.commit('initialiseStore') }
})
2️⃣
.use(router)
.use(store)
3️⃣
.mount('#app')
demo
Side note: Since you're migrating to Vue 3, Pinia is now the officially recommended state management library that replaces Vuex (now deprecated). See Pinia's migration guide.

Created Lifecycle Hook of global vue instance

I want to be able to use the AOS library globally on my vue project.
This is for Vue 2.
new Vue({
created () {
AOS.init()
},
render: h => h(App),
}).$mount('#app');
The Vue 3 sets up the app a little bit different.
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
I dont have that created option with the Vue 3 setup. I tried this, but it´s more of a guessing game...
createApp({App, AOS.init()})
But do I make this work in Vue 3?
You can still do that in Vue 3. Note h() is now imported as a global function from vue instead of being an argument of render().
Here's the equivalent Vue 3 code:
import { createApp, h } from 'vue'
import App from './App.vue'
createApp({
created() {
AOS.init()
},
render: () => h(App),
}).mount('#app')
You could use the created hook of the root component. To me that has always seemed like an appropriate place to initialize application-wide libraries.

Which way better to create vue component (export default vs defineComponent vs new Vue)

After learning Vue.js lately, i'm pretty match confused about how to write vue component syntax
i keep seeing youtube tutorials, as well as articles, and everyone uses a different approach.
in terms of vue 3
should we use
export default to create a component
or export default defineComponent
or new Vue({
so how to decide the right way on how to create App component and the rest of its child components and pages etc ..
Hopefully my question is clear enough.
Thanks
If you need to create multiple components I would highly recommend using Single File Components (SFC)
Here you define a new component as (inside the <script> tag):
import { defineComponent } from 'vue'
export default defineComponent({
// ...
})
(or export default {} if not using TypeScript)
For the main app component you would do this:
import { createApp } from "vue";
const app = createApp(App)
app.mount('#app')
OR just like this, if you don't need to extent Vue with vue-router, Vuex etc.
import { createApp } from "vue";
createApp(App).mount('#app')

How do I do to make multi-pages switch smoothly in Vue.js with a navigation bar? How to router in MPA project?

I'm learning Vue.js 2.6.Here is my basic directory:
I need my home and blogs shares the same header and footer, so I imported my header and footer components separately in my home.vue and blogs.vue, but It didn't switch page smoothly when I click the link in the navigation bar. What can I do to make it smooth?
To make this project I turned to some case on the internet, after that I was confused when I saw its Router file structure:
It seems that I'm coding it as a MPA, but why is that index.js in Routers dir needed?
my home.js as below:
import Vue from 'vue'
import Home from './home.vue'
import router from '../../router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
el: '#homeDiv',
router,
components: { Home },
template: '<Home/>',
render:h => h(Home)
});
my index.js in Router dir as below:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from 'HelloWorld'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'App',
component: HelloWorld
}
]
})
and there's another main.js in the root of src dir, the author of that sample code did nothing to the initial App.vue and main.js. I just added some element-ui related code into index.js and main.js.
main.js:
import Vue from 'vue';
import App from './App';
import router from './router';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
//import './plugins/element.js'
Vue.config.productionTip = false;
Vue.use(ElementUI);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
new Vue({
el: '#app',
render:h => h(App)
})
I felt its Router looks like spaghetti, I can't see which code is needed, which is not. What is a GOOD Router structure in a vue.js MPA project?
THX
You have multiple questions being asked here.
What is the best router structure for vue-router?
I don't think there is a standard anywhere. A lot of codes I have seen adopted the style you have already. Which is fine depending on the scale of what you are building.
How to make a smooth transition between pages?
In my projects, I wrap the router-view component in the official vue transition component. As advised here in the official vue router documentation
Please let me know if these answers suffice.

showing Vue is not defined error while importing vue-router

I have created a new project using vue-cli 'vue init webpack-simple my-app' command. In that fresh installation copy, I'm trying to import vue-router in the App.vue component that was created by default. But it is giving me an error: 'Uncaught ReferenceError: Vue is not defined'. If I import the vue again in App.vue, then the app is working fine. But I already imported the vue in main.js, so why do I need to import it again in App.js? Is there any way I can use the imported vue from main.js? Here is my code:
main.js:
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})
App.vue:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import Vue from 'vue'; //**why I need to import it again? I already imported it in main.js
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import QuestionOne from './components/QuestionOneTemplate';
const routes = [
{ path: '/', name: 'QuestionOne', component: QuestionOne },
];
const router = new VueRouter({
routes
});
window.router = router;
export default {
router,
name: 'app',
data () {
return {
}
}
}
</script>
<style lang="scss">
</style>
Is there any way i can use the imported vue from main.js?
No, you need to import it in every file that uses Vue. The imports/requires are how things get hooked up. Rest assured, each import will be the same singleton instance.
You can get to the router from a Vue component's javascript using this.$router and this.$route without an import, or inside a template, using simply $router and $route
Not recommended, but you can assign Vue to a global in main.js, and use the global without importing.
main.js
import Vue from 'vue';
global.MyVue = Vue
App.vue
import VueRouter from 'vue-router';
MyVue.use(VueRouter);
Why
This is how ES6 links things up. Consider it wiring. If there were more than 1 Vue lib available, how would the linker know which to use? What if another library defined a variable or function called Vue? Perhaps a lib uses its own internal Vue for an event bus or other feature.
Other Thoughts
The explicit import also makes IDE autocompletion and syntax highlighting work better. Some IDEs can add the imports automatically, and that makes life easier.
did you try this ?
import Vue from 'vue'
import VueRouter from 'vue-router'
then use
Vue.use(VueRouter)
because the error message means you need to import vue first to use vue-router
You did the right thing and you don't have to worry about importing Vue in multiple files. When you are shipping your application and build it for production, you will have only one "Vue import". If you take a look at dist folder and your bundled .js files you will notice that Vue is imported only once.