Created Lifecycle Hook of global vue instance - vue.js

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.

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.

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

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.

Vuejs different kinds of entry points are confusing

I created two Vuejs project.
The 1st one main.js looks like this:
import Vue from 'vue'
import App from './App.vue'
import BootstrapVue from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
The second one looks like this:
import Vue from "vue";
import App from "./App";
import router from "./router";
import BootstrapVue from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: "#app",
router,
components: { App },
template: "<App/>"
});
please someone explain me the difference between this codes espacially the the new vue instance creation in two differnt ways?
For The 1st one main.js:
First you must understand all the render:
The render: h => h(App) is shorthand for:
render: function (createElement) {
return createElement(App);
}
Which can be shortened to:
render: (createElement) => {
return createElement(App);
}
Which can again be shortened to (with h being an alias to createElement as noted above):
render: (h) => {
return h(App);
}
Which is then shortened further to (using ES6 "fat arrow" syntax):
render: h => h(App);
The H, It comes from the term "hyperscript", which is commonly used in many virtual-dom implementations. "Hyperscript" itself stands for "script that generates HTML structures" because HTML is the acronym for "hyper-text markup language".
And the $mount allows you to explicitly mount the Vue instance when you need to. This means that you can delay the mounting of your vue instance until a particular element exists in your page or some async process has finished, which can be particularly useful when adding vue to legacy apps which inject elements into the DOM, I've also used this frequently in testing when I've wanted to use the same vue instance across multiple tests:
// Create the vue instance but don't mount it
const vm = new Vue({
template: '<div>I\'m mounted</div>',
created(){
console.log('Created');
},
mounted(){
console.log('Mounted');
}
});
// Some async task that creates a new element on the page which we can mount our instance to.
setTimeout(() => {
// Inject Div into DOM
var div = document.createElement('div');
div.id = 'async-div';
document.body.appendChild(div);
vm.$mount('#async-div');
},1000)
For The second one, I strongly recommend you to look over the current Vue documentation:
https://v2.vuejs.org/v2/guide/instance.html
Having all of your template code in an App.vue (and none in your index.html’s #app div) allows us to use the runtime-only version of Vue which is smaller than the full version.
but lets break it up:
el: '#app', will look in your index.html file for a div <div id="app"></div>;
the router, will allow you to use globally the router;
components: { App }, import your App.vue, and all component you have imported there, generally you put in this file people often put: side bar components, headers components, navigable stuff;
4.template: "<App/>", will create a div in you HTML with the id="app" only after it import you App.vue components imported there or HTML created in this file, all the content from you files will be wrapped by this div. People often use <router-view> to load the router pages components.
This second instance have the purpose of Having a cleaner index.html and having all the stuff in the App.vue

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.

Need an example vue-router (vue 2.x) for a Layout.vue with other route based components

I cannot figure out how to set this up properly using vue-router with vue.js 2.x
I want App.vue to be a main site layout module which contains basic site level things like footer, logo, main nav, etc.
A route based architecture which will load components based on the route inside this App.vue
ie: /things to show list and /things/:id to show individual item
I'm using the webpack template from vue-cli
I'm confused about main.js vs. App.vue should I be moving the routes out of main.js into App.vue?
Can someone link to a simple hello world using layouts in vue-router?
import Vue from 'vue'
import App from './App'
import Items from './components/Items'
import Item from './components/Item'
import Axios from 'axios'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
Vue.prototype.$http = Axios
const routers = new VueRouter([
{ path: '/items/:id', component: Item },
{ path: '/', component: Items }
])
// how to specify App.vue as a layout?
new Vue({
routes
}).$mount('#app')
I think this should work for you
const app = new Vue({
router,
render: (h) => h(App)
}).$mount('#app')
or spread operator
const app = new Vue({
router,
...App
}).$mount('#app')
As I mentioned in comment, take look at the repo that I created https://github.com/bedakb/vuewp/tree/master/public/app/themes/vuewp/app
I had wrong property name:
new Vue({
router,
...App
}).$mount('#app')
This fixes it. I had imported it as routes not router. Another way to fix would have been { router: routes } but I renamed the file to router and now everything works.
Big thanks to #belmin for hoping on screenhero to try and help me fix it!